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

Создание ролевой компьютерной игры 54) Клавиатурное управление, сохранение/восстановление


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

54) Клавиатурное управление, сохранение и восстановление

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

  // -----
  procedure TGameForm.FormKeyUp(Sender: TObject; var Key: Word; Shift:
  TShiftState);
  begin

  case Key of

     VK_LEFT: MoveHero( -1,0 );
    VK_RIGHT: MoveHero( +1,0 );
       VK_UP: MoveHero( 0,-1 );
     VK_DOWN: MoveHero( 0,+1 );

  end;

  ShowGame;
  end; //

Игра сразу ожила - персонаж перемещается по карте, останавливаясь перед непроходимыми тайлами. Все прекрасно скроллируется и отображается, а возможные небольшие перемаргивания связаны с вызовом процедуры ShowGame, отображающей все игровое поле полностью. Коммерческие программы выполняют такое отображение с помощью быстрых графических библиотек наподобие DirectX. Перенос в DirectX, кстати, может быть даже проще переноса в стандартный интерфейс Delphi, так как в нем не используется так активно механизм событий, а анализ нажатия пользователем клавиш и, соответственно, схема управления, аналогичны принципу DOS-версии, изложенной в модуле Main. Впрочем, и в нашем случае объем переделок совсем невелик.

Следующим шагом добавим и все остальные функции:

  ...

  VK_TAB: NextHero;

       ord( ' > ' ): GoToNextLevel(+1);
       ord( ' < ' ): GoToNextLevel(-1);

       ord( ' C ' ): ShowHeroFullInfo;

       ord( ' G ' ): GetItemFromMap;

       ord( ' E ' ): ShowHeroSlots;

       ord( ' I ' ): ShowHeroItems;

       ord( ' J ' ): ShowJournal;

       ord( ' M ' ): ShowGlobalMap;

       ord( ' T ' ): ThrowSpell;

       ord( ' S ' ): SaveGame;
       ord( ' L ' ): LoadGame;

       ord( ' A ' ): HeroShot(-1,0);
       ord( ' D ' ): HeroShot(+1,0);
       ord( ' W ' ): HeroShot(0,-1);
       ord( ' Z ' ): HeroShot(0,+1);

  ...

Единственное дополнение здесь связано с формой представления кода нажатой клавиши - оно выражено в символьной форме, поэтому мы воспользовались функцией ord(), переводящей символ в его код.

Однако пока почти все эти процедуры у нас не реализованы, точнее, представлены "пустышками". А вот процедуры SaveGame и LoadGame можно использовать один в один, без какой-либо модификации, так как возможности Delphi по работе с файлами совместимы с версиями Borland Pascal. Из первоочередных потребуется вывод короткого сообщения - создадим его в виде стандартного всплывающего окошечка Windows:

  { ----------------- }
  procedure ShowInfo(Msg: string) ;
  begin
  ShowMessage(Msg);
  end;

Процесс игры становится сразу значительно более понятным.

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

  { ----------------- }
  procedure ShowHeroInfo(HeroNum: Integer);
  begin
  GameForm.Label1.Caption :=
    STR_HERO_HP+ IntToStr(Heroes[HeroNum].HP) + ' / ' +
  IntToStr(Heroes[HeroNum].MaxHP);
  GameForm.Label2.Caption :=
   STR_HERO_MANA + IntToStr(Heroes[HeroNum].Mana)+ ' / '
  +IntToStr(Heroes[HeroNum].MaxMana);
  GameForm.Label3.Caption :=
    STR_HERO_XY + IntToStr(Heroes[HeroNum].x) + ' , ' +
  IntToStr(Heroes[HeroNum].y);
  end;

Сохраненные в DOS-варианте функции сохранения и восстановления можно "привязать" непосредственно к выбору соответствующих пунктов меню. Добавим в меню такие пункты - "Сохранить" и "Восстановить", а также два невизуальных компонента OpenDialog и SaveDialog. В код процедур обмена с файлами вместо прямого обращения к единому имени файла sav.dat запишем возможность выбора любого имени файла пользователем:

  { ----------------- }
  procedure SaveGame;
  var F: File;
      i: Integer;
  begin
  if not GameForm.SaveDialog1.Execute then Exit;

  Assign(F,GameForm.SaveDialog1.FileName);
  Rewrite(F,1);

  for i := 1 to MaxItems do
    BlockWrite(F, Items[i], SizeOf(Items[i]));

  for i := 1 to MaxHeroes do
    BlockWrite(F, Heroes[i], SizeOf(Heroes[i]));

  BlockWrite(F, CurHero, SizeOf(CurHero));

  BlockWrite(F, GameMap, SizeOf(GameMap));
  BlockWrite(F, CurMap, SizeOf(CurMap));

  for i := 1 to MaxMonsters do
    BlockWrite(F, Monsters[i], SizeOf(Monsters[i]));

  for i := 1 to MaxQuests do
    BlockWrite(F, Quests[i], SizeOf(Quests[i]));

  Close(F);

  ShowInfo(STR_SAVEOK);
  end;

  { ----------------- }
  procedure LoadGame;
  var F: File;
      i: Integer;
  begin

  if not GameForm.OpenDialog1.Execute then Exit;

  Assign(F,GameForm.OpenDialog1.FileName);
  Reset(F,1);

  for i := 1 to MaxItems do
    BlockRead(F, Items[i], SizeOf(Items[i]));

  for i := 1 to MaxHeroes do
    BlockRead(F, Heroes[i], SizeOf(Heroes[i]));

  BlockRead(F, CurHero, SizeOf(CurHero));

  BlockRead(F, GameMap, SizeOf(GameMap));
  BlockRead(F, CurMap, SizeOf(CurMap));

  for i := 1 to MaxMonsters do
    BlockRead(F, Monsters[i], SizeOf(Monsters[i]));

  for i := 1 to MaxQuests do
    BlockRead(F, Quests[i], SizeOf(Quests[i]));

  Close(F);

  ShowInfo(STR_LOADOK);
  ShowGame;
  end;

Продолжим перенос кода из DOS-раздела в Windows-версию. Следующей процедурой, нуждающейся в небольшой адаптации, будет подпрограмма обработки гибели героя.

  { ----------------- }
  procedure HeroDied;
  var i: Integer;
  begin
  ShowInfo(STR_HERO_DIED);

  for i := 1 to MaxHeroes do
   if Heroes[i].HP > 0 then
      begin
      NextHero;
      Exit;
      end;

  Application.Terminate; // завершение приложения
  end;

Далее займемся переносом работы с инвентарем. Она будет выполняться в отдельной форме.

Исходный код текущей версии (в ней обновлены картинки предметов, которые прислал Александр Аргунов):

dw090208.zip , 29974 байта.

Только картинки там никудышные, символические) Вместо правильных изображений ничего нету пока. Если кто найдет/нарисует посимпатичнее, присылайте.


(c) 2004-2008 Сергей Бобровский : bo собака russianenterprisesolutions.com

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

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


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


В избранное