Как сделать массив в инвентаре

Обновлено: 02.07.2024

Разрабатывая игры, в особенности РПГ, возникает необходимость создания рюкзака для артефактов найденных в игровом мире, а также некоторые артефакты и оружие должны иметь возможность надевания на персонажа. Появляется куча вопросов, а как же это все запрограммировать на делфи?

Все очень легко и просто. Инвентарь представляет собой набор ячеек, пронумерованных и связанных друг с другом. Слоты для одежды персонажа также представляют собой набор ячеек, но не связанных между собой. В любой игре любые наборы чего-либо реализуются в виде массивов.

Массив – это как раз и есть набор отдельных ячеек. А тип этих ячеек определяет тип хранимой информации:

· String – текстовая информация.

· Integer – хранятся целые числа.

· Char – в одной ячейке может быть лишь один символ.

· Real – хранит дробные числа.

Итак, мы разобрались, что данные мы будем хранить в массивах. Теперь определимся с типом данных и размером массивов. Допустим у нашего героя находится рюкзак (инвентарь), рассчитанный на 5 ячеек. Значит и наш массив будет также рассчитан на 5 ячеек. Нумеровать ячейки мы будем с нуля. Информацию мы будем хранить целочисленную. Каждая цифра будет показывать номер вещи, которая лежит в ячейке. Если ячейка пуста – в ячейке хранится цифра ноль.

Поэтому первым делом объявляем наш массив для инвентаря:

Inventar:array[0..4] of integer;

Переменная I необходима, чтобы в цикле обнулить наш массив, так как он пустой. Можно делать это без цикла, но зачем писать больше строчек кода. Обнуляем наш инвентарь:

Как же теперь добавлять предметы в рюкзак (инвентарь) героя? Заполнение должно происходить при торговле когда мы покупаем артефакты, при нахождении артефактов (вещей) или при других вариантах. Мы рассмотрим вариант когда герой наступает на артефакт и он попадает в наш инвентарь.

Допустим у нас имеется массив карты Map [ I , j ] и массив артефактов Arts [ I , j ]. Тогда при движении персонажа мы в массиве Map проверяем может ли герой наступить на следующую ячейку, а в массиве Arts проверяем не находится ли в следующей ячейке какого-нибудь артефакта.

Например у нас есть на карте ячейки:

Наш герой не может ходить по воде (к примеру). Значит при движении делаем следующую проверку:

В нашем случае x и y – это координаты клеточки, на которую хочет стать наш персонаж. Если в массиве карты с координатами х и у содержится цифра больше нуля (а значит там нет воды) – передвигаем героя в нужную клетку.

А теперь сразу после проверки на воду, делаем проверку на артефакты (вещи):

If Arts[x,y]>0 then

If (Inventar[i]=0) and (Arts[x,y]>0) then

В нашем случае если в массиве с вещами оказывается какая-либо вещь (массив содержит цифру больше нуля) – номер этой вещи присваиваем в первую свободную ячейку, а клеточку массива вещей обнуляем, чтобы предмет пропал с карты.

А что делать если в каждой ячейке может храниться несколько вещей одного типа, например 3 лука или 10 стрел, или 2 золотых монеты. В таком случае наш массив инвентаря должен быть двухмерным. То есть должен содержать два уровня. Первый (верхний уровень) у нас будет работать также как и раньше – будет содержать номера вещей, а второй уровень (нижний) будет содержать количество предметов. Поэтому массив инвентаря будет выглядеть так:

Inventar:array[0..4, 1..2] of integer;

Теперь первая цифра означает номер ячейки, а вторая номер уровня. Например:

Inventar [1,1] – отображает номер вещи если она есть

Inventar [1,2] – отображает количество вещей

Теперь проверка на артефакты также изменится следующим образом:

If Arts[x,y]>0 then

If (Inventar[I,1]=0) and (Arts[x,y]>0) then

If (Inventar[I,1]= Arts[x,y]) and (Arts[x,y]>0) then

Как видно из выше приведенного кода теперь кроме номера вещи в верхний уровень, добавляется и количество в нижний уровень. И довилась еще одна проверка. Первая проверка проверяет если есть артефакт и инвентарь пуст то доавляем артефакт в инвентарь. А вторая проверка проверяет, если слот в инвентаре уже содержит один из таких вещей, то такую вещь также посещает в этот слот, и увеличиваем количество на единицу.

На этом предлагаю закончить нашу работу с инвентарем. Главное Вы поняли смысл работы с ним. Останется только выводить графику самого инвентаря и вещей, находящихся в нем. Но как это сделать мы уже говорили в предыдущих статьях.

Следующий вопрос, волнующий нас – это как вещи с инвентаря одевать в слоты одежды на персонажа? Для начала также создадим массив для слотов одежды:

Dress : array [0..4] of integer ;

Как видно из кода выше, мы имеем лишь четыре слота для одежды. Это лишь для примера. Условимся, что:

· Первый слот – головные уборы

· Второй слот – нагрудники

· Третий слот – обувь

· Четвертый – оружие в руке

Также Вы заметили, что массив одномерный. Это потому что нам нужно знать лишь номер артефакта, а его количество и так не может быть больше единицы. Оно или надето или его нет вообще. Хотя возможны случаи если нужно отображать время до поломки оружия или нагрудника или степень поломки, также можно отображать харктеристики одежды типа анти-магия, защита и так далее. Для этого мы просто можем добавить дополнительные уровни в массив и все. Но мы не будем так углубляться.

В начале наш массив также должен быть обнулен, так как одежды нет на герое. Затем, чтобы одеть одежу нам нужно кликнуть по картинке одежды в рюкзаке и сделать проверку может ли данная вещь быть надета на персонажа, если да, то в какой слот для одежды и не занят ли он?

Условимся, что номера 1-20 – это головные уборы, 21-30 – нагрудники, 31-40 – обувь, 41-60 – это оружие, 61-100 – другие вещи. Допустим, что мы знаем по какому слоту инвентаря кликнул игрок (например по слоту 2), тогда проверка будет следующая:

If (Inventar[2]>0) and (Inventar[2]

Эта проверка сделана для головных уборов. В нашем случае мы сразу одеваем предмет и обнуляем ячейку инвентаря даже если там таких предметов несколько. Следующая проверка для нагрудников:

If (Inventar[2]>20) and (Inventar[2]

If Inventar[2,2]=0 then Inventar[2,1]:=0;

Для нагрудников проверка сделана более правильно. Сначала мы одеваем артефакт, затем в ячейке с артефактом уменьшаем количество предметов на единицу. Затем проверяем если предметов там уже нет, то есть храниться ноль – удалям предмет из инвентаря вообще. Таким же образом делаем и для других вещей.

Еще одетые предметы могут добавлять какие-то характеристики персонажу. В таком случае при одевании нужно сделать проверку на номер вещи и определить что она добавит. Рассмотрим подобный вариант с оружием в реку. Допустим что мы знаем, что оружие с номером 61 добавляет силу +5. Тогда пишем так :

If (Inventar[2]>20) and (Inventar[2]

if Inventar[2]=61 then Personazh.Sila:= Personazh.Sila+5;

If Inventar[2,2]=0 then Inventar[2,1]:=0;

Еще очень важный аспект – не забывайте при снятии артефактов уменьшать характеристики персонажа, которые они добавляли ему. Иначе можно будет просто много раз одевать предмет и до бесконечности прокачивать главного героя.

На этом у меня все. Я конечно же не смог поговорить и показать все, что можно сделать. Но зато Вы уже будете иметь преставление о том как сделать инвентарь для персонажа, как с ним работать, как сделать слоты для одежды и как их одевать на персонажа артефакты из рюкзака. Все спасибо за внимание и удачи в создании игр на делфи!

Сейчас на странице 0 пользователей

Нет пользователей, просматривающих эту страницу.

Было что то подобное у Интермеха делал примочку, та кона и дырки делала. Тогда Тоолбохх не делал в деталях 1-3 например насквозь или с обработкой.

Дружище ! Классная штука, а можно мне чуток пределать куда она пишет значения ? в конфиг или настройки? Мне нужно в настроки! Можно отдельно сделать . В личке можем обсудить детали.

Snake 60

Подскажите где найти литературу по программированию на HAAS о которой вы говорите? В книжке нашей не нашёл макросы

Предлагаю свое решение, для любых форматов файлов в которое вписывается все что хочешь не трогая имя файла, иначе путаница и имя устанешь вписывать все то что можно.. NTFS поток прекрасно позволяет туда писать, можно и файлы вкладывать. StreamPDM.zip позволяет вставлять в фалы другие файлы такие как чертежи и зд модели или фотки или наоборот , разницы нет. mpdm2_0.zip Записывает любые значения как пользовательские поля в SW , только формат не имеет значения и данные пtреносятся автоматом из пользовательских полей , меню в ТС изменение атрибута в значение одного WDX указывается второй WDX, таким образом можно переносить данные в разные плагины например SW в mPDM. Можно "брать" данные из файла и "вносить" в другие файлы.. Скажем данные из спецификаци по количеству изделий в сборке макрос есть что прописывает для каждой сборки и общее количество. Им и можно оперировать из полей пользователей, а потом вносить в DWG\DXF В Total commander можно тул бар сделать и кнопки с нужными данными для файлов вносить сразу без шаблонов из атрибутов. Я просто привык к атрибутам. Для каждого САПР свой wdx плагин (Компас есть, SW 2014 и ниже есть) Что касается версий новых то зачитать из SW файлов 2015 -2022 есть плагины что зачитываю только Shelldetals.wdx, Shellinfo.wdx (я не пользуюсь ими) На фотке я вношу в разные форматы файлов значения от файла SW , любые значения которые можно. Потом я так же одним действием вношу данные в mPDM и уже "распространяю" в любые файлы. Кстати SW файлы так же можно внести данные которые повторяются и тд (ПОКА ЧТО нет SW плагина WDX для 2015 и выше версий.) Кто то может и напишет для SW 2020 или 2022 . Да, забыл не имеет значения в Total commander тип WDX плагина все стандартно и одинаково.. так что все что раньше был под SolidWorks.wdx , тоже самое работает и с mPDM.wdx поиск, сортировка, переименования, фильтр быстрый, придать цвет файлу по данным из имении или из содержимого WDX.

Snake 60

@vksenia611 Если утрировать, то в солиде есть два типа размеров: 1) Это размеры импортированные из модели в чертеж. Изменяя их в чертеже, Вы можете напрямую влиять/изменять размер модели 2) Это справочные размеры, которые Вы сами проставляли вручную. Так вот "уезжают" или "слетают" в основном они, если в процессе изменения модели исчез тот элемент (грань, кромка, вершина) к которому они были привязаны. Исправляется или перетаскиванием и привязкой точки размерной линии на новый элемент, или удалением подвисшего размера и простановкой нового, что иногда бывает намного быстрее, чем исправлять поехавшие )




Приступаем к скриптингу.
Создаем новый скрипт с именем Item, где будем хранить все характеристики предмета. Их у нас будет целых две :): название предмета и его иконка. Думаю для начала этого хватит, вы по желанию можете любые переменные и значения добавлять. Приступим к редактированию скрипта. Во-первых наш класс ничего не наследует поэтому удаляем MonoBehaviour.Создаем две переменные типа Texture2D и string , которые будут содержать иконку и название предмета. Наш скрипт выглядит так:

using UnityEngine;
using System.Collections;

[System.Serializable]
public class Item

public Texture2D Textura; //текстура иконки
public string Name; //название
>


Обязательно добавляем [System.Serializable]
Создаем еще один скрипт и называем его ItemData. В нем будем хранить предметы, а так же создавать их для инвентаря. Первым делом подключаем пространство имен System.Collections.Generic, что бы можно было использовать списки.
Код:

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class ItemData : MonoBehaviour

public static ItemData _ItemData; //паттерн Singelton
public List Items = new List (); //списк в котором хранятся предметы

void Awake()
<
_ItemData = this;
>

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class ItemData : MonoBehaviour

public static ItemData _ItemData; //паттерн Singelton
public List Items = new List (); //списк в котором хранятся предметы

void Awake()
<
_ItemData = this;
>

//генерация предмета
public Item ItemGen(int win_id)
<
Item item = new Item();
item.Name = Items[win_id].Name;
item.Textura = Items[win_id].Textura;
return item;
>
>

Вешаем наш скрипт на камеру (в принципе не важно куда его вешать) В инспекторе создаем 4 предмета. Называем их и задаем иконки и названия.



Теперь перейдем непосредственно к созданию инвентаря. Создаем скрипт и называем его Inventory. Создаем переменные отвечающие за размер ячеек, окна инвентаря и кол-во ячеек. У нас будет 6 колонок по 4 ячейки, итого 24 ячейки.

using UnityEngine;
using System.Collections;

public class Inventory : MonoBehaviour

const int INVENTORY_WINDOW_ID = 1; //id окна инвентаря

public float ButtonWidth = 40; //высота ячейки
public float ButtonHeight = 40; //ширина ячейки

int invRows = 6; //количество колонок
int invColumns = 4; //количество столбцов
Rect inventoryWindowRect = new Rect(10, 10,
170, 265); //область окна


Добавляем еще несколько вспомогательных переменных для возможности передвигать предметы и создаем словарь содержащий наши предметы и принимающий в качестве ключа int .
(не забываем добавить System.Collections.Generic для работы со словарями).

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class Inventory : MonoBehaviour

const int INVENTORY_WINDOW_ID = 1; //id окна инвентаря

public float ButtonWidth = 40; //высота ячейки
public float ButtonHeight = 40; //ширина ячейки

int invRows = 6; //количество колонок
int invColumns = 4; //количество столбцов
Rect inventoryWindowRect = new Rect(10, 10,
230, 265); //область окна
bool isDraggable; //возможно ли перемещение предмета
Item selectItem; //вспомогательная переменная куда заносим предмет инвентаря
Texture2D dragTexture; //текстура которая отображается при перетягивании предмета в инвентаре

Dictionary InventoryPlayer = new Dictionary (); //словарь содержащий предметы инвентаря

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class Inventory : MonoBehaviour

const int INVENTORY_WINDOW_ID = 1; //id окна инвентаря

public float ButtonWidth = 40; //высота ячейки
public float ButtonHeight = 40; //ширина ячейки

int invRows = 6; //количество колонок
int invColumns = 4; //количество столбцов
Rect inventoryWindowRect = new Rect(10, 10,
230, 265); //область окна
bool isDraggable; //перемещается ли айтем?
Item selectItem; //вспомогательная переменная куда заносим предмет инвентаря
Texture2D dragTexture; //текстура которая отображается при перетягивании предмета в инвентаре

Dictionary InventoryPlayer = new Dictionary (); //словарь содержащий предметы инвентаря

Update is called once per frame
void Update ()

void OnGUI()
<
inventoryWindowRect = GUI.Window(INVENTORY_WINDOW_ID, inventoryWindowRect, firstInventory, "INVENTORY"); //создаем окно
>

void firstInventory(int id)
<
for (int y = 0; y InventoryPlayer = new Dictionary (); //словарь содержащий предметы инвентаря

void Start () <
//добавляем предметы в инвентарь
InventoryPlayer.Add(0, ItemData._ItemData.ItemGen(0));
InventoryPlayer.Add(1, ItemData._ItemData.ItemGen(1));
InventoryPlayer.Add(2, ItemData._ItemData.ItemGen(2));
InventoryPlayer.Add(3, ItemData._ItemData.ItemGen(3));
>

// Update is called once per frame
void Update ()

void OnGUI()
<
inventoryWindowRect = GUI.Window(INVENTORY_WINDOW_ID, inventoryWindowRect, firstInventory, "INVENTORY"); //создаем окно
>

void firstInventory(int id)
<
for (int i = 0; i InventoryPlayer = new Dictionary (); //словарь содержащий предметы инвентаря

По просьбе решил написать простой туториал о создании кастомного инвентаря игрока. Прочитав данную статью, я подумал сделать свой инвентарь но с многими изменениями и под новую версию майна.

Туториал предполагает что вы знакомы с использованием прокси и умеете общаться с CAP`ой на уровне жестов(если не умеете то будем учить), а как отправлять пакеты постараюсь пояснить

Инвентарь, который получиться будет выглядеть так:


Это будет отдельный инвентарь(т.е. он не будет перекрывать обычный), который мы сможем открыть по нажатию созданной нами в дальнейшем кнопки Н. Для повышения совместимости кнопку сделаем так, что ее можно будет поменять в настройках управления на другую, таким образом любой пользователь сможет настроить все как ему удобно.

  1. CustomInventory.java - класс который будет управлять содержимым инвентаря, например: хранение, сохранение и восстановление инвентаря, управление предметами и т.д..
  2. ContainerCustomInv,java - контейнер. В нем будут добавляться слоты и описываться механика перетаскивания предметов из слота в слот при шифт-клике на них.
  3. StandartSlot.java - кастомные слоты, которые будем добавлять в контейнер. Хотя можно использовать и ванильные, но заодно покажу как использовать свои.
  4. GUICustomInv.java - то, как будет выглядеть инвентарь(бинд текстуры и прочее).

Для того, чтоб вы не путались с индексами слотов когда будете делать или менять контейнер, я прикреплю такую картинку в помощь. На ней все слоты промаркированные:


Теперь нужно настроить контейнер:

Пару слов о том, как ориентироваться в размещении слотов. Слоты, которые мы добавляем в инвентарь стандартного размера(16 x 16). Когда добавляем слот( this.addSlotToContainer(new StandartSlot(player, cInventory, 0, x, y)) , указываем x и y координаты, на которых этот слот будет размещен. В качестве центра выступает левый верхний угол слота. Думаю, понятнее будет, если посмотреть на картинку ниже:


Как видно на картинке, желтые точки это точки с координатами x и y, которые указывались при добавлении слота. Красным отмечен контур слота и как он располагается относительно указанной точки. Здесь я добавил два слота, с координатами x = 0, y = 0 и x = 87, y = 8.

Читайте также: