Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

Создание ролевой компьютерной игры 55) Работа с инвентарем


Школа программирования

55) Программирование ролевой игры: Работа с инвентарем

Работа с инвентарем должна выполняться в отдельной форме, на которой расположим список и две кнопки "Использовать" и "Бросить". А поле-метка MoneyLabel будет ответственно за отображение текущей наличности. Тем самым мы полностью дублируем задачу, решаемую DOS-версией кода.

Создадим новую форму, назовем ее InvForm. Разместим на ней список и назовем его ListBox. Добавим также метку MoneyLabel для вывода текущей суммы денег, кнопку UseButton с заголовком "Использовать", по нажатию на которую будет взят элемент из инвентаря, кнопку DropButton с заголовком "Бросить".

Все действия по работе с инвентарем "погрузим" в код этой формы. Одно из действий, которое наверняка будет требоваться многократно - это формирование списка предметов и вывод текущей суммы наличности. Назовем такой метод - ShowItemList:

  // -----
  procedure TInvForm.ShowItemList;
  var fg,i,n,s: Integer;
  begin
  ListBox.Clear;
  for i := 1 to MaxHeroItems do
    begin
    if Heroes[CurHero].Items[i].IType = itemNone
       then ListBox.Items.Add(STR_EMPTY_ITEM)
       else ListBox.Items.Add( GetItemName(Heroes[CurHero].Items[i]) )
    end;

  i := GetMoneyNo(Heroes[CurHero]);
  if i > 0
     then MoneyLabel.Caption :=
  IntToStr(Heroes[CurHero].Items[i].Ints[intMoney])+ ' $ '
     else MoneyLabel.Caption := ' 0 ' ;
  end; //

Из текущей процедуры будем лишь вызвать форму к отображению (после подготовки списка инвентаря):

  { ----------------- }
  procedure ShowHeroItems;
  begin
  InvForm.ShowItemList;
  InvForm.ShowModal;
  end;

Процедура использования предмета почти не отличается от DOS-версии:

  // -----
  procedure TInvForm.UseButtonClick(Sender: TObject);
  var fg,i,n,s: Integer;
  begin
   n := ListBox.ItemIndex+1;

   if Heroes[CurHero].Items[n].IType = itemAmmo then
        begin
        if Heroes[CurHero].Slots[slotHands].IType = itemRangedWeapon then
           begin
           Heroes[CurHero].Slots[slotHands].Ints[intRangedAmmo] :=
             Heroes[CurHero].Slots[slotHands].Ints[intRangedAmmo] +
             Heroes[CurHero].Items[n].Ints[intAmmo];
           Heroes[CurHero].Items[n].IType := itemNone;
           ShowItemList;
           end
        end else

     if Heroes[CurHero].Items[n].IType = itemEat then
        begin
        fg := Heroes[CurHero].Fatigue;
        fg := round( fg * (95-random(21))/100 );
        Heroes[CurHero].Fatigue := fg;
        Heroes[CurHero].Items[n].IType := itemNone;
        ShowItemList;
        ShowInfo(STR_FATGOOD + IntToStr(fg));
        end else

     if not UseMagikItem(n) then
        begin
        s := GetFreeSlot(Heroes[CurHero],Heroes[CurHero].Items[n]);
        if s > 0 then
           begin
           Heroes[CurHero].Slots[s] := Heroes[CurHero].Items[n];
           Heroes[CurHero].Items[n].IType := itemNone;
           ShowItemList;
           end;
        end;

  end; //

Схожа ситуация и с кодом избавления от предмета:

  // -----
  procedure TInvForm.DropButtonClick(Sender: TObject);
  var n,s: Integer;
  begin
    s := GetFreeItemNum;
    n := ListBox.ItemIndex+1;
    if s > 0 then
       begin
       Items[s] := Heroes[CurHero].Items[abs(n)];
       Items[s].x := Heroes[CurHero].x;
       Items[s].y := Heroes[CurHero].y;
       Heroes[CurHero].Items[abs(n)].IType := itemNone;
       ShowItemList;
       end;
  end; //

Подобный подход, с созданием отдельной формы, применим и к подпрограмме отображения содержимого слотов персонажа (что на нем одето и что у него в руках). Создадим новую форму и назовем ее SlotForm. Разместим на этой форме список ListBox и кнопку InvButton ("В инвентарь").

Создадим в ней процедуру заполнения списка обмундирования:

  // -----
  procedure TSlotForm.ShowItemList;
  var i: Integer;
  begin
  ListBox.Clear;
  for i := 1 to MaxSlots do
    begin
    if Heroes[CurHero].Slots[i].IType = itemNone
       then ListBox.Items.Add(STR_EMPTY_ITEM)
       else ListBox.Items.Add( GetItemName(Heroes[CurHero].Slots[i]))
    end;
  ListBox.ItemIndex := 0;
  end; //

Добавим обработчик нажатия на кнопку "В инвентарь":

  // -----
  procedure TSlotForm.InvButtonClick(Sender: TObject);
  var s,n: Integer;
  begin
  n := ListBox.ItemIndex+1;
  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;
     ShowItemList;
     end;
  end; //

Вызов самой формы вставим в процедуру ShowHeroItems:

  { ----------------- }
  procedure ShowHeroItems;
  begin
  InvForm.ShowItemList;
  InvForm.ShowModal;
  end;

Код процедуры ShowHeroFullInfo также будет связан с новой формой - назовем ее FullInfoForm. Но так как интерактивных элементов в нем нету - лишь выводятся сведения о персонаже, достаточно разместить текстовое поле Memo с выключенным режимом редактирования, и кнопку закрытия. А заносить информацию будем непосредственно в модуле LowLevel.

  { ----------------- }
  procedure ShowHeroFullInfo;
  var i: Integer;
  begin
  with FullInfoForm do
   begin
   Memo.Clear;
   Memo.Lines.Add(Heroes[CurHero].Name+ ' , ' +
          RaceName[Heroes[CurHero].Race]+ ' ' +
          ClassName[Heroes[CurHero].HeroClass]);
   Memo.Lines.Add(STR_HEROFI_LEVEL+ IntToStr(Heroes[CurHero].Level));
   Memo.Lines.Add(STR_MAPFI_LEVEL+ IntToStr(CurMap));
   Memo.Lines.Add(STR_HEROFI_EXP+ IntToStr(Heroes[CurHero].Exp)+ ' /
  ' +IntToStr(Heroes[CurHero].MaxExp));
   Memo.Lines.Add(STR_HEROFI_FAT+ IntToStr(Heroes[CurHero].Fatigue)+ '
  / ' +IntToStr(MAX_FATIGUE));
   Memo.Lines.Add( ' ' );
   for i := 1 to MaxChars do
    Memo.Lines.Add( CharsName[i]+ ' : ' + IntToStr(Heroes[CurHero].Chars[i]) );

   Memo.Lines.Add( ' ' );
   for i := 1 to MaxSkills do
    Memo.Lines.Add( SkillsName[i]+ ' : ' + IntToStr(Heroes[CurHero].Skills[i]) );
   ShowModal;
   end;
  end;

Потребует реализации на базе новой формы и функция GetSpellNo - в ней надо выбрать заклинание для использования. Создадим новую форму SpellForm, управлять действием будем двумя стандартными кнопками - OK при запуске выбранного заклинания и Cancel при отказе. Добавим на форму список ListBox.

Модификация списка заклинаний у нас не выполняется - пользователь должен лишь выбрать заклинание и нажать кнопку OK, поэтому создавать специальную процедуру формирования такого списка не будем, так как он всегда одинаков. Поэтому весь код обработки можно оставить в модуле LowLevel.

  { ----------------- }
  function GetSpellNo: Integer;
  var i: Integer;
  begin

  SpellForm.ListBox.Clear;

  for i := 1 to MaxSpells do
    SpellForm.ListBox.Items.Add(Spells[i].Name+ ' : ' +IntToStr(Spells[i].Mana));
  SpellForm.ListBox.ItemIndex := 0;

  if SpellForm.ShowModal = mrOk
     then GetSpellNo:=SpellForm.ListBox.ItemIndex+1
     else GetSpellNo:=0;

  end;

Теперь, после написания данного кода, у нас в Windows сразу стал работоспособен очередной режим игры - за магов.

На очереди - задача кодирования работы магазина.

Исходный код текущей версии:

dw300308.zip , 34654 байта.


(c) 2004-2008 Сергей Бобровский

Школа программирования с нуля
Все предыдущие выпуски базового курса всегда тут:
http://www.infiltration.ru/p/

Неофициальный сайт поддержки (со срочными вопросами - сюда):
www.prog-begin.net.ru.


Мои книги (учебные курсы) "Технологии Delphi / C++ / C#".
http://shop.piter.com/publish/authors/17681/191180213/
Дизайн рассылки: Алексей Голубев - Web-дизайн и web-программирование


В избранное