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

Создание ролевой компьютерной игры 25) Магия - начинаем


Информационный Канал Subscribe.Ru

Разработка ролевой игры

25) Магия - начинаем

Последний из нереализованных нами классов, и важная область игры - магия. На первый взгляд может показаться, что ее реализация потребует большого объема работы, однако мы уже хорошо продумали и отладили механизмы расширения навыков героя, и введение новых навыков и умений не потребует каких-либо кардинальных переделок и улучшений.

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

Добавим персонажу две новые характеристики - по аналогии с уровнем здоровья, Mana и MaxMana:

  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;
       x,y,
       HP, MaxHP,
       Mana, MaxMana,
       Exp, MaxExp,
       Level, VisLong: Integer;

       Class, Race: Integer;

       Name: String[20];
       end;

Мана должна формироваться и расти вместе с показателями здоровья, хотя для некоторых классов (в нашем случае - для класса воина) способность к магии должна быть запрещена, как того требуют классические ролевые системы. А у стрелка она должна быть развита слабо. В ходе анализа соответствующего кода мы выясним, что у нас пока не реализована разница в здоровье для персонажей разных классов. Для уровня здоровья задействован один массив HPLevel_Table, в котором нет дополнительного деления на классы (впрочем, он создавался, когда о классах мы еще не задумывались). Давайте такое дополнение введем:

  const HPLevel_Table: array
            [classWarrior..classMage,
             0..MaxPlayerLevel] of Integer =
    (
    (10, 20, 30, 50, 80, 130, 210, 340),
    (8, 12, 20, 30, 50, 100, 150, 250),
    (4, 7, 10, 15, 30, 50, 100, 175)
    );

Сразу дополним модуль Tables и массивом уровней маны в зависимости от классов:

  const ManaLevel_Table: array
            [classWarrior..classMage,
             0..MaxPlayerLevel] of Integer =
    (
    (0, 0, 0, 0, 0, 0, 0, 0),
    (4, 7, 10, 15, 30, 50, 100, 175),
    (8, 12, 20, 30, 50, 100, 150, 250)
    );

Во всех местах, которые теперь будут компилироваться с ошибками, нам надо будет исправить обращение к массиву уровней здоровья на уточненный вызов с указанием класса, а также добавить код работы с уровнем маны. Часть команд из процедуры InitHero (инициализация HP, MaxHP) перенесем для удобства в конец GenerateHero, так как теперь нам нужно знать выбранный класс героя. Тут же разместим инициализацию уровня маны:

  ...
  with Heroes[CurHero] do
    begin
    MaxHP := HPLevel_Table[Class,Level];
    HP := MaxHP;
    Mana := ManaLevel_Table[Class,Level];
    MaxMana := Mana;
    Exp := 0;
    MaxExp := ExpLevel_Table[Level];
    VisLong := 2;
    end;

  end;

Схожий код исправим и откорректируем в процедуре IncXP (модуль Hero):

  { ----------------- }
  procedure IncXP( var H: THero; axp: Integer );
  begin
  inc( H.Exp, axp );
  ShowInfo(STR_ADD_EXP + IntToStr(axp));
  if H.Exp > H.MaxExp then
     begin
     H.Exp := 0;
     if H.Level < MaxPlayerLevel then
        begin
        ShowInfo(STR_NEXTLEVEL);
        inc(H.Level);
        end;
     H.MaxExp := ExpLevel_Table[H.Level];
     H.MaxHP := HPLevel_Table[H.Class,H.Level];
     H.MaxMana := ManaLevel_Table[H.Class,H.Level];
     H.HP := H.MaxHP;
     end;
  end;

Также добавим строку вывода уровня маны в процедуру динамического отображения информации о герое ShowHeroInfo:

  { ----------------- }
  procedure ShowHeroInfo(HeroNum: Integer);
  begin
  TextColor( LightGray );
  GoToXY(40, 2);
  Write(STR_HERO_HP,Heroes[HeroNum].HP, ' / ' ,Heroes[HeroNum].MaxHP);
  GoToXY(40, 3);
  Write(STR_HERO_MANA,Heroes[HeroNum].Mana, ' / ' ,Heroes[HeroNum].M
  axMana);
  GoToXY(40, 4);
  Write(STR_HERO_XY,Heroes[HeroNum].x, ' , ' ,Heroes[HeroNum].y);
  end;

Константа STR_HERO_MANA:

  STR_HERO_MANA = ' Мана/Макс.Мана: ' ;

Как мана будет расходоваться? Расходоваться она будет на заклинания. А заклинания - товар штучный, их сложно уложить в прокрустово ложе описания структуры. Работа заклинания - процесс оригинальный и будет реализовываться непосредственно в программном коде.

Для демонстрации возможностей магической системы создадим два заклинания. Первое, назовем его "Огненный шторм", будет наносить повреждения от 1 до 4 единиц каждому монстру, находящемуся на любой соседней с героем клеток, а второе - "Самоисцеление", позволит быстро восстановить собственное здоровье. За счет маны, конечно.

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

Далее - создаем заклинание "Огненный шторм".


Исходный код текущей версии для Turbo Pascal (всегда проверен и работоспособен, главный файл - main.pas):

http://russianenterprisesolutions.com/sbo/download/1176.zip 12028 байт


(c) 2004-2006 Сергей Бобровский bobrovsky@russianenterprisesolutions.com

Школа программирования с нуля
Все предыдущие выпуски базового курса тут:
http://russianenterprisesolutions.com/sbo/

Дизайн рассылки: Алексей Голубев - Web-дизайн и web-программирование


Subscribe.Ru
Поддержка подписчиков
Другие рассылки этой тематики
Другие рассылки этого автора
Подписан адрес:
Код этой рассылки: comp.soft.prog.prognull.game
Архив рассылки
Отписаться Вебом Почтой
Вспомнить пароль

В избранное