forum.boolean.name

forum.boolean.name (http://forum.boolean.name/index.php)
-   FAQ (http://forum.boolean.name/forumdisplay.php?f=15)
-   -   Инвентарь (http://forum.boolean.name/showthread.php?t=12671)

Nex 15.06.2010 07:58

Инвентарь
 
В этой статье вы узнаете, как создать инвентарь. Статья расщитана для тех, кто уже знает основы..
Однажды мне захотелось сделать инвентарь, как в играх и я пошел на Blitz Et Cetera, прочитав там 2 статьи я научился делать инвентарь и мне захотелось сделать свой и более универсальный инвентарь. После того, как он был сделан, я решил написать мою первую статью на булке.
Для урока на понадобится картинки (пустая ячейка инвентаря и картинки вещей инвентаря), но если вы не умеете или не знаете где их взять или как их нарисовать, то можете взять мои.
  1. Картинка пустой ячейки инвентаря
  2. Батарейки
  3. Пузырь с ядом
  4. Древние монеты
;--------------------------------------------------------------
Начинаем.
;--------------------------------------------------------------
;Создаем начальные переменные.
Код:

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 файлы
Код:

Include "INIfunc.bb"
Создаем массив для инвентаря
Код:

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, а то сколько боюсь уже и вроде не много понял суть, но на "выходе" получается какая нибудь фигня. :(

Nex 15.06.2010 08:11

Ответ: Инвентарь
 
Вложений: 1
По поводу иклуда INIfunc.bb и его функций.
Русские символы не держит. :(

Записывает в указанный файл значения
SetIniItem ("settings.ini","group1","x",50)
  • group1 - как будет называться стобец
  • x - срока в которой будет значение
  • 50 - само значение

Получает инфу из указанного файла
GetIniItem ("data\settings.ini","group1","y")
  • group1 - название столбца
  • y - строка со значение
стобец - :-). не знаю чем это слово заменить.
з.ы. ниже этот инклуд. :rolleyes:

is.SarCasm 15.06.2010 09:40

Ответ: Инвентарь
 
У меня только один вопрос! Зачем? Уже есть очень хорошая статья по инвентарю на цетере.

Arton 15.06.2010 17:29

Ответ: Инвентарь
 
Цитата:

Сообщение от Igorian (Сообщение 150266)
У меня только один вопрос! Зачем? Уже есть очень хорошая статья по инвентарю на цетере.

Ну мне кажется здесь более подробно...

Randomize 15.06.2010 17:40

Ответ: Инвентарь
 
Там не понял - здесь поймёшь или наоборот.
Igorian,
Цитата:

прочитав там 2 статьи я научился делать инвентарь и мне захотелось сделать свой и более универсальный инвентарь

Nex 16.06.2010 10:33

Ответ: Инвентарь
 
Не много отредактировал первый пост ибо получилось очень много ошибок в тексте. :) И кстати кому нибудь эта статья помогла? :-)

Randomize 16.06.2010 19:57

Ответ: Инвентарь
 
У нас тут все уже давно умные стали.
Им не угодишь.

is.SarCasm 16.06.2010 20:26

Ответ: Инвентарь
 
Новичков нету просто.

Arton 17.06.2010 17:23

Ответ: Инвентарь
 
Цитата:

Сообщение от Igorian (Сообщение 150409)
Новичков нету просто.

Я новичок! Но мне сейчас не до инвентаря, не говоря уже о блице...

Colossus 18.11.2012 05:41

Ответ: Инвентарь
 
мне помогла, хоть чуть чуть разобрался )))


Часовой пояс GMT +4, время: 07:04.

vBulletin® Version 3.6.5.
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Перевод: zCarot