Меню сайта
Форма входа

Категории раздела
Уроки по созданию игр [38]
Программирование игр разной сложности
Игровые алгоритмы [24]
Алгоритмы, которые уже реализованы для разных жанров игр
Графика [5]
Учимся работать с графикой в Делфи
Мультимедиа [3]
Работа с мультимедийными возможностями Делфи
Другие статьи [18]
Статьи не вошедшие не в один из разделов
Ошибки [4]
Всевозможные ошибки и пути их решения
Пятница, 01.11.2024, 03:03
Приветствую Вас Гость

Статьи по программированию

Главная » Статьи » Уроки по созданию игр

Урок 15. Рюкзак и инвентарь-2

 Урок 15. Рюкзак и инвентарь-2

 

Давайте снабдим героя в начале игры двумя предметами - легкой броней и недорогим топором. Положим эти предметы ему в рюкзак с помощью следующих операторов процедуры InitHero:

 

procedure  InitHero(HeroNum:   Integer); var  i:   Integer; begin

with   Heroes[HeroNum]   do begin for  i   :=   1   to  MaxChars   do

Chars [i]    :=   0; for  i   :=   1   to MaxSkills   do

Skills [i]    :=  BaseSkill_Table[i];

For i:=1 to MaxHeroItems do

Items[i].IType:=ItemNone;

Items[i]:=ItemTypes[1];

Items[i]:=ItemTypes[4];

 

Предметами, хранящимися в рюкзаке героя, стали топор и броня. Эти предметы нам надо будет перемещать из рюкзака на тело и в руки героя.

Нам потребуется еще один массив, который мы назовем Slots, элементы которого будут соответствовать предметам, непосредственно используемым героем. Это броня или оружие. В коммерческих играх список носимых предметов обычно сопровождается кольцами, цепочками, колчаном, оружейным поясом, отдельными артефактами для рук (наручи), ног (поножи), специализированными видами оружия. Можно и самостоятельно реализовать в игре такую возможность по описанной структуре ТНего:

 

Const

slotSlots=2;

slotBody=1;

slotHands=2;

 

Type

THero=record

Chars:array[1..MaxChars] of integer;

Skills:array[1..MaxSkills] of integer;

Items:array[1..MaxHeroItems] of TGameItem;

Slots:array[1..MaxSlots] of TGameItem;

End;

 

Два слота (броня на теле и оружие в руках), доступ к которым может производиться с индексов slotBody и slotHands. Проинициализируем этот массив в InitHero:

 

Procedure InitHero (HeroNum:   Integer);

Var i:integer;

Begin

  For i:=1 to Items[HeroNum] do

  Begin

  For i:=1 to MaxChars do

  Chars[i]:=0;

  For i:=1 to MaxSkills do

  Skills[i]:=BaseSkill_Table[i];

  For i:=1 to MaxHeroItems do

  Items[i].IType:=ItemNone;

  Items[i]:=ItemTypes[1];

  Items[i]:=ItemTypes[4];

 

  For i:=1 to MaxSlots do

  Items[i].IType:=ItemNone;

  End;

End;

 

Массив слотов просто представим набором "пустых" предметов. Для носимых героем предметов подготовим процедуру ShowHeroSlots (модуль

 

Procedure SHowHeroSlots;

Var i:integer;

begin

…_SLOT ITEMS) ;

For i:=1 to MaxSlots do

begin    . ..

GoToXY(l,i+2); Write(SlotName[i],    '    :    '    );

if Heroes[CurHero].Slots[i].IType  =   itemNone then Write(STR_EMPTY_ITEM)

else

Write(Heroes[CurHero].Slots[i].Name)

end;

GoToXY(l,20); ReadLn; ShowGame;

end;

 

Константа STR_HERO_SLOTITEMS должна быть описана в модуле Texts:

 

const STR_HERO_SLOTITEMS  =   '   Используемые   героем предметы:    '    ;

 

Массив констант SlotName (названия слотов героя) опишем также в модуле Texts:

 

const SlotName:   array[1..MaxSlots]   of string[20]   = ('   Тело   '    ,    '   В   Руках   ' );

 

Внесение этой константы в программу может вызвать определенные трудности. Дело в том, что она использует другую константу - MaxSlots, которая описана в модуле Hеrо. Попытка добавить ссылку на модуль Него в interface-заголовок модуля Texts закончится неудачно из-за того, что возникает замкнутая кольцевая цепочка ссылок interface-разделов друг па друга. Модуль Texts ссылается на модуль Него, а тот в свою очередь - на модуль Gameltem, которому снова требуется сслыка на Texts, так как в его интерфейсной части расположены описания массива типовых предметов ItemTypes, поле Name которого требует указания константы из модуля Texts.

Сейчас мы решим эту проблему "в лоб". Переместим описание константы MaxSlots, из-за которой разгорелся весь сыр-бор, в модуль Texts (хотя это и не совсем корректно в смысловом плане):

 

const MaxSlots   =   2;

SlotName:   array[1..MaxSlots]   of string[20]   = ('   Тело   '    ,    '   В   Руках   ' ) ;

 

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

 

MaxSlots: unit Hero;

interface  uses  Gameltem,    Texts;

 

Одновременно убрав ее из раздела реализации.

Теперь программа соберется без проблем. Однако, как уже говорилось, такой подход, хотя и достигает цели, но все же не может считаться оптимальным. Ведь модуль Texts предназначен для хранения только текстовых констант, и подобное смешение понятий может по мере усложнения программы привести к новым ошибкам подобного класса. Правильнее спрятать подробное описание массива ItemTypes в раздел реализации модуля Gameltem, переместив туда же и ссылку на модуль Texts, а доступ к элементам ItemTypes обеспечить с помощью дополнительной функции - например, GetltemType, возвращающей элемент массива по его номеру (параметру функции). Вы сами можете дополнить программу такой возможностью.

Вызов процедуры ShowHeroSlots введем в обработчик нажатий на клавиши в главном модуле программы Main. Пусть список надетых героем предметов показывается при нажатии на клавишу 'e':

 

While Item do

Begin

SHowItem;

I:ReadKey;

Case i of

‘i’ : ShowHeroSlots;

‘j’ : SHowHeroItems;


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

Ложим предметы в рюкзак.

Дополним возможности списка надетых предметов дополнительными возможностями. Позволим

задавать команды - например, ввод номера слота будет означать команду "предм с этим номером убрать в рюкзак". Для этого в процедуре ShowHeroSlots добавим возможность просмотра, а также выделим основную часть процедуры в бесконечный цикл, который будет зацикливаться когда пользователь введет в качестве номера ноль.

 

Procedure ShowHeroSlots;

Var I,n:integer;

Begin

While True do

… (readln)

…(1, 1);

…_Hero_SlotItmes);

For i:=1 to MaxSlots do

Begin

(retaky)…(1,i+2)

Write (i, ‘ ) ‘ , SlotName[i], ‘ : ‘ );

If Heroes [CurHero].Slots[i].IType = itemNone

Then Write(STR_EMTY_ITEM)

Else Write(Heroes[CurHero].Slots[i].Name);

End;

… (1, 20);

 Write (‘>’);

…(0);

If n=0 then break;

End;

End;

 

Значение надо проверить. Если слот пуст, или в рюкзаке нет места, никаких действий принимать не надо. В противном случае (в слоте есть предмет и в рюкзаке свободные места) переместим предмет в рюкзак. Проверка пустоты слота несложна, а проверку свободного места в рюкзаке желательно реализовать в виде отдельной функции. Заметим, что данная реализация будет в значительной степени зависеть от способа того места в рюкзаке. Этот способ может содержать анализ веса груза, местоположения предмета в рюкзаке и так далее. Поэтому выделим GetFreeBag, возвращающую номер свободного элемента в рюкзаке или ноль. Запишем функцию в модуле Него:

 

Procedure GetFreeBag (var H:Hero): Integer;

Var i:integer;

Begin

GetFreeBag:=0;

for   i   : = 1   to  MaxHeroItems do

if  H.Items[i].IType   =  itemNone   then

begin

GetFreeBag   :=   i;

Exit

end;

end;

 

В ней происходит перебор предметов, хранящихся в рюкзаке, и как только обнаруживается элемент, у которого значение поля IType соответствует значению типа "пустого" предмета, функция возвращает его индекс в массиве Items, входящего в структуру Него. С учетом этих нововведений процедура ShowHeroSlots запишется так:

 

procedure   ShowHeroSlots;

var  i,n,s:   Integer;

begin

while  true  do begin ClrScr;

GoToXY(l,1);

Write(STR_HERO_SLOTITEMS) ;

for   i   :=   1   to  MaxSlots   do

begin

GoToXY(l,i+2);

Write(i,        )    '    ,SlotName[i],    '    :    '    );

if  Heroes[CurHero].Slots[i].IType   =   itemNone then 

Write(STR_EMPTY_ITEM)

else

Write(Heroes[CurHero].Slots[i].Name)

end;

GoToXY(l,20);Write(    '   >   '    ); ReadLn(n);  

if  n  =   0   then

break;

s   :=  GetFreeBag(Heroes[CurHero]);

if   (Heroes[CurHero].Slots[n].IType   <>   itemNone)   and   (s   >   0)   then

begin

Heroes[CurHero].Items[s]    :=  Heroes[CurHero].Slots[n];

Heroes[CurHero].Slots[n].IType   :=  itemNone;

end;

end;

ShowGame;

end;

 

После того, как введенный номер слота проверен и выяснено, что он корректен, скопируем соответствующий элемент массива Slots в найденный незанятый элемент рюкзака (массив Items), после чего пометим элемент Slots[n] как "пустой".

Далее: Одеваем предметы из рюкзака.


Источник: delgame.at.ua

Категория: Уроки по созданию игр | Добавил: Armageddets (06.12.2013) | Автор: Урок 15. Рюкзак и инвентарь-2
Просмотров: 1265 | Теги: складывам предметы в инвентарь, Рюкзак и инвентарь игрового персона, Урок 15 | Рейтинг: 0.0/0
Всего комментариев: 0
Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]
Наш опрос
Какие уроки по созданию игр Вам удобнее?
Всего ответов: 141
Мини-чат
Друзья сайта
  • Официальный блог
  • Сообщество uCoz
  • FAQ по системе
  • Инструкции для uCoz
  • Статистика

    Онлайн всего: 1
    Гостей: 1
    Пользователей: 0