В этой статье вы узнаете, как создать инвентарь. Статья расщитана для тех, кто уже знает основы..
Однажды мне захотелось сделать инвентарь, как в играх и я пошел на
Blitz Et Cetera, прочитав там 2 статьи я научился делать инвентарь и мне захотелось сделать свой и более универсальный инвентарь. После того, как он был сделан, я решил написать мою первую статью на булке.
Для урока на понадобится картинки (пустая ячейка инвентаря и картинки вещей инвентаря), но если вы не умеете или не знаете где их взять или как их нарисовать, то можете взять мои.
- Картинка пустой ячейки инвентаря
- Батарейки
- Пузырь с ядом
- Древние монеты
;--------------------------------------------------------------
Начинаем.
;--------------------------------------------------------------
;Создаем начальные переменные.
Global GWidth% = 1024, GHeight%=768 ; Размер/разрешение экрана (Ширина, высота)
Global GridW% = 8, GridH% = 4 ;Размер инвентаря (Ширина, высота)
Создадим основу примера
Graphics GWidth, GHeight, 32, 2
SetBuffer BackBuffer ()
SeedRnd (MilliSecs ())
While Not KeyHit (1)
Cls ()
;
Flip
Wend :End
Ширина и высота окна у нас берется из переменных созданных выше
Двойная буфферизация
Полный рандом
И цикл игры
Подключаем файл с помощью которого будем читать
.ini файлы
Создаем массив для инвентаря
Dim Grid (GridW+1,GridH+1)
Создаем типы.
; Временный тип. Для хранения параметров
Type TItemTemp
Field ID%,image,desc$
End Type
; Тип для хранения вещей (итемов)
Type TItem
Field ID,ItemID,image,desc$
Field x%,y%,amount,status
Field OldX%,OldY%
End Type
Создаем еще переменные
Global defImg = LoadImage ("defInvSlot.png") ; Загружаем картинку пустой ячейки инвентаря
MaskImage defImg,1,1,1 ;Устанавливаем ей маску (так как фон у картинки черный, а по дефолту черный фон не рисуется.)
Global font = LoadFont ("Arial",15,1) :SetFont (font) Загружаем и устанавливаем шрифт.
Global ItemW%=32, ItemH%=32 ;Размер ячейки инвентаря (ширина, высота).
Global TempInvImg ;доп. переменные
Global MaxItem% ;Сколько всего будет вещей (Итемов) в игре.
Global InvX%=0,InvY%=0 ;Начальные координаты рисования инвентаря.
Global TempItemID%, TempItemID2%, TempItemID3%, SetID% = False,mouse ;тоже доп. переменные
Теперь надо загрузить предметы (итемы).
Ниже функция, которая считывает информацию о предметах из файла (Содержимое файла будет ниже).
Функция сначала узнает сколько всего предметов, а потом их загружает/создает.
Function GetItems (link$) ;Название функции и путь до файла.
temp$ = "item" ;Переменная внутри функции, которая содержит название искомой строки.
num%=1
amount =0
If FileType (link$)=True Then ; Если указанный файл существует, то начинаем...
file = ReadFile (link$) ;Сначала открываем файл
For i=1 To 50 ;Создаем цикл от i=1 до 50 (50 - это макс. кол-во предметов в игре. Можно ставить хоть 100500.)
temp2$ = ReadLine (file) ;Считываем файл
If Not temp2$ Then Exit ;Если файл закончился, то выходим из цикла
If Mid (temp2$,2,4) = "item" Then ;Если нашли нужную нам строку, то..
amount = amount +1 ;добавляем 1 (один) к переменной "amount".
EndIf
Next
CloseFile (file) ; Обязательно закрываем файл!
MaxItem% = amount% ;Общее кол-во найденных предметов в файле.
For i=1 To amount% ;Создаем цикл от i=1 до amount (кол-во найденных предметов)
it.TItemTemp = New TItemTemp ;Заполняем временный тип
it\ID% = Handle (it) ;Запоминаем хендл
it\image$ = LoadImage (GetIniItem$ (link$,temp$+num%,"image")) ;Загружаем изображение ячейки полученное из файла. Используетcя переменная "temp" и "num".
MaskImage it\image,255,0,255 ;Маска изображения. У меня фон ячеек розовый ибо цвет яркий и в основном не используется в изображения.
it\desc$ = GetIniItem (link$,temp$+num%,"desc") ;Получаем описание ячейки из файла.
num% = num% +1 ;Прибавляем 1 (один) к переменной "num" для получения след. строки.
Next ; выход из цикла.
EndIf
End Function
Содержимое файла с информацией о предметах.
Создайте файл с названием например "dat.ini" и скопируйте в него ниже идущий код
[item1] ;"Название" вещи
image=slotm.png ;Картинка вещи
desc=Ancient Money ;Описание вещи
[item2]
image=mm1.png
desc=Poison
[item3]
image=battery.png
desc=Default battery
Можно добавить еще параметров типа: стоймость, вес и т.д.
Вставьте эту строку перед циклом.
GetItems ("dat.ini") ;Название функции и путь до файла содержащего описание предметов.
Если все заработало, то будем продолжать дальше.
Ниже идет функция отрисовки инвентаря.
Function DrawInventory (sx%,sy%) ;Название функции и начальные координаты инвентаря.
For x=1 To GridW ;Цикл от i=1 до GridW (ширина инвенторя)
For y=1 To GridH ;Цикл от i=1 до GridH (высота инвенторя)
DrawImage defImg,sx+x*ItemW,sy+y*ItemH ; рисуем изображение пустой ячейки
;defImg - переменная в которой загружено изображение пустой ячейки, sx+x*ItemW - НачальнаяПозицияХ+х (шаг цикла)*ШиринаИзображения
Next
Next
End Function
Вставьте строку DrawInventory (sx%,sy%) в цикл игры
While Not KeyHit (1)
Cls ()
DrawInventory (InvX,InvY) ;Как было написано выше строки InvX,InvY - это начальные координаты инвентаря.
Flip
Wend :End
Теперь создадим функцию обновления инвентаря
Function RefreshInventory ()
For x=0 To GridW
For y=0 To GridH
grid (x,y)=0 ;Заполняем массив нулями ибо в нем пока что ничего не лежит.
Next
Next
For item.TItem = Each TItem
it.TItem = Object.TItem (item\ID)
If it\status =1 Then ;Если параметр вещи "it\status" равен 1 (одному), то..
grid (it\x,it\y)=it\ID ;Ячейка массива (инвентаря) в котором она лежит равна "ID" вещи.
EndIf
Next
; Если курсор находится "над инвентарем", то..
If MouseX() > InvX%+ItemW% And MouseX() < InvX+ItemW%*(GridW%+1) And MouseY() > InvY%+ItemH% And MouseY() < InvY%+ItemH%*(GridH%+1) Then
If MouseDown (1) Then ;Если нажата и удерживается левая кнопка мыши
If grid ((MouseX()-InvX%)/ItemW%,(MouseY()-InvY%)/ItemH%) <> 0 Then ;и если ячейка массива над которым находиться мышь больше или меньше нуля (если ячейка не пустая), то..
TempItemID = grid ((MouseX()-InvX%)/ItemW%,(MouseY()-InvY%)/ItemH%) ;присваиваем переменной "TempItemID" "ID" вещи находящейся в ячейке над которой находится мышь.
If TempItemID2 = 0 Then ;Если переменная "TempItemID2" равна нулю, то..
it.TItem = Object TItem (TempItemID)
it\status=False ;Меняем статус вещи на "False" (ноль)
If it\OldX <> it\x Then it\OldX = it\x ;запоминаем "старые" координаты картинки
If it\OldY <> it\y Then it\OldY = it\y ;пригодится потом..
TempInvImg = it\image ;копируем изображение вещи. Нужно при перемещении вещи.
If TempItemID2 = 0 Or TempItemID2 <> TempItemID Then SetID = True :If SetID = True Then TempItemID2 = TempItemID :SetID = False
If TempItemID2 <> 0 Then mouse=True ;если TempItemID2 <> 0 значит "подцепили какую то вещь, меняем mouse на mouse=True
EndIf
EndIf
Else ; если отпустили левую кнопку мыши
If mouse=True Then ;и переменная mouse=True (одному)
it.TItem = Object TItem (TempItemID2)
If grid ((MouseX()-InvX%)/ItemW%,(MouseY()-InvY%)/ItemH%) = 0 Then ;и если мышь находится над пустой ячейкой инвентаря, то..
it\x = (MouseX()-InvX%)/ItemW% ;координата "x" вещи равна ячейке пустой ячейке инвентаря над которой находится мышь
it\y = (MouseY()-InvY%)/ItemH% ;координата "y" вещи равна ячейке пустой ячейке инвентаря над которой находится мышь
it\OldX = it\x ;обновляем "старые" координаты на новые
it\OldY = it\y ;обновляем "старые" координаты на новые
it\status = True ;меняем статус вещи на "True"
TempItemID2 = 0 ;обнуляем переменную
mouse = False ;меняем переменную mouse на ноль
Else ; если мышь находится над не пустой(!) ячейкой инвентаря
If mouse = True Then ; и переменная mouse = True, то..
it\x = it\OldX ;возврящаем вещь на старую "x" координату
it\y = it\OldY ;возврящаем вещь на старую "y" координату
it\status = True ;меняем статус вещи на "True"
TempItemID2 = 0 ;обнуляем переменную
mouse = False ;меняем переменную mouse на ноль
EndIf
EndIf
EndIf
EndIf
EndIf
End Function
Фух.
Теперь надо обновить функцию DrawInventory (sx%,sy%).
Function DrawInventory (sx%,sy%)
For x=1 To GridW
For y=1 To GridH
DrawImage defImg,sx+x*ItemW,sy+y*ItemH
Next
Next
For item.TItem = Each TItem
For i=1 To MaxItem
If item\status = 1 Then DrawImage item\image,sx+item\x*ItemW,sy+item\y*ItemH ;если статус вещи равен "True" (если вещь не перемещается), то рисуем ее.
Next
Next
If MouseX() > InvX%+ItemW% And MouseX() < InvX+ItemW%*(GridW%+1) And MouseY() > InvY%+ItemH% And MouseY() < InvY%+ItemH%*(GridH%+1) Then ;если курсор над инвентарем
If MouseDown (1) And TempInvImg <>0 Then DrawImage TempInvImg,MouseX (),MouseY () ;и нажата левая кнопка мыши и переменная TempInvImg больше или меньше 0 (нуля), то рисуем временное(!) изображение в позии курсора.
TempItemID3 = grid ((MouseX()-InvX%)/ItemW%,(MouseY()-InvY%)/ItemH%) ;копируем "ID" вещи
If MouseDown(1)=False And TempItemID3 <> 0 Then DrawItemInfo (TempItemID3) ;если не нажата(!) левая кнопка мыши и TempItemID3 больше или меньше нуля, то показываем описание вещи
;ниже идет функция отвечающая за описание вещи
EndIf
End Function
С помошью этой функции рисуем описание вещи рядом с курсором.
Function DrawItemInfo (ID%) ;Название функции и "ID" вещи.
it.TItem = Object.TItem (ID%)
If it\desc$ <> 0 Then ;если описание вещи больше или меньше нуля, то..
Color 100,50,0 ;устанавливаем цвет
RectHeight = FontHeight () ;получаем размер шрифта
RectWidth = StringWidth (it\desc$)+6 ;получаем длину строки
x# = MouseX ()+5 ;получаем координаты курсора
y# = MouseY ()-10 ;получаем координаты курсора
Rect x,y,RectWidth,RectHeight ;рисуем прямоугольник
DrawText (it\desc$,x+3,y) ;и в этом прямоугольнике рисуем описание.
; прямоугольник русуется для того чтобы текст был хорошо виден.
EndIf
End Function
В выше идущей функции используется функция DrawText () - эта функция сделана чтобы для смены цвета текста не нужно было каждый раз писать "Color 1,2,3".
Вот код этой функции
Function DrawText (msg$,x#,y#,red%=255,green%=255,blue%=255) ;думаю понятно что и как..
Color red,green,blue
Text x#,y#,msg$
End Function
Теперь ставим функции DrawInventory () и RefreshInventory () в цикл
While Not KeyHit (1)
Cls ()
RefreshInventory ()
DrawInventory (InvX,InvY)
Flip
Wend :End
Чего то не хватает. Ах да, я не написал как создать вещь.
Function NewItem (x,y,ItemID%) ;x и y - в какой ячейке инвентаря создать вещь, ItemID - номер вещи которую создать.
item.TItem = New TItem
item\ID = Handle (item) ;ID вещи
item\ItemID = ItemID% ;номер создаваемой вещи
item\x = x ;позиция по "x"
item\y = y ;позиция по "y"
; а вот тут мы ищем "ID" вещи равной параметру "ItemID"
tit.TItemTemp = Object.TItemTemp (ItemID%)
item\image = tit\image$ ;копируем изображение
item\desc$ = tit\desc$ ;копируем описание
item\status = 1 ;и устанавливаем статус вещи на 1 (один)
End Function
И для удобства я создал еще одну функцию, которая автоматически "ставит" вещь в самую первую пустую ячейку инвенторя.
Function AddItem (ItemID%)
Local NeedExit = False ;переменная для выхода из второго цикла
For y=1 To GridH
For x=1 To GridW
If grid (x,y) = 0 Then ;если ячейка массива равна нулю, то
grid (x,y) = ItemID% ;присваиваем ей "ItemID" вещи
NewItem (x,y,1,ItemID%) ;функция создания вещи
NeedExit = True ;меняем на True
Exit ;выходим из первого цикла
EndIf
Next
If (needExit = True) Then Exit ;выходим из второго цикла
Next
End Function
Ну и сделаем чтоб при нажатии на "пробел" создавалась случайная вещь
If KeyHit (57) Then AddItem (Rand (3)) ;цифра 3 обозначает сколько у вас всего вещей и через команду "Rand" выбирается случайное целое(!) число от 1 до 3.
Ну вот наверно и все. Надеюсь, что написал все, что хотел и у вас все будет работать.
з.ы. Имеется большая просьба.
Напишите, пожалуйста статью про поиск пути в 3D, а то сколько боюсь уже и вроде не много понял суть, но на "выходе" получается какая нибудь фигня.