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

Создание ролевой компьютерной игры 21) Герой готовится к жизни


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

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

21) Герой готовится к жизни

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

Процесс генерации, создания героя, даже с точки зрения пользователя сам по себе важен и обычно занимает немало времени. В классических системах типа AD&D этот процесс различными способами упрощается - так, человеку предлагается выбрать одну из предопределенных рас и один из предопределенных классов героя (воин, лучник, маг, вор и тому подобные). Воин крепок здоровьем и хорошо дерется ручным оружием, но плохо стреляет и совсем не способен к магии. Лучник прекрасно стреляет, похуже сражается в ближнем бою, и также не владеет волшебством. Маг обычно совсем хил, и в реальном бою любого вида сразу проигрывает, зато магией владеет в совершенстве. Бывают смешанные классы - например, паладин совмещает воина и мага. А некоторые расы более приспособлены к определенному виду деятельности - например, эльфы мастерски стреляют из лука, гномы хорошо дерутся в ближнем бою. А человек (игровая раса) обычно считается потенциально равным для всех видов деятельности.

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

Будем придерживаться этой идеи и мы. Вдумчивый читатель без труда дополнит предлагаемую нами схему реализации возможностью настраивать те или иные параметры вручную.

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

  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,
       Exp, MaxExp,
       Level, VisLong: Integer;

       Class, Race: Integer;
       end;

Первое из них, Class, укажет на класс героя, второе - Race - на его расу. Допустим, у нас будет три класса - воин, лучник и маг, и четыре расы - человек (равно способный ко всему), эльф (способный к стрельбе из лука), гном (способный к рукопашному бою) и хоббит (способный к магии). Соответственно, подготовим константы этих понятий в модуле Hero:

  const
  ...
        raceHuman = 1;
        raceElf = 2;
        raceDwarf = 3;
        raceHobbit = 4;

        classWarrior = 1;
        classRanger = 2;

Константы, задающие число рас и классов, а также массивы с названиями этих понятий на русском языке сразу заведем в модуле Texts:

  const
  ...

  MaxRace = 4;
  RaceName: array[1..MaxRace] of string[15] =
  (
  ' Человек ' , ' Эльф ' , ' Гном ' , ' Хоббит '
  );

  MaxClass = 3;
  ClassName: array[1..MaxClass] of string[15] =
  (
  ' Воин ' , ' Стрелок ' , ' Маг '
  );

Кроме того, разрешим указывать имя героя, что сделает игру значительно более человечной. Для этого в структуре героя добавим новое поле Name длинной 20 символов:

  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,
       Exp, MaxExp,
       Level, VisLong: Integer;

       Class, Race: Integer;

       Name: String[20];
       end;

Теперь нам нужна процедура, которая будет осуществлять начальное распределение всех параметров и выбор расы, класса и имени. Назовем ее GenerateHero, вызывать будем из главного модуля, в самом начале игры, сразу после процедуры инициализации героев InitHero:

  begin
  Randomize;

  VideoInitialize;
  MapGeneration(1);
  GenerateMonsters;
  InitHeroes;
  GenerateHero;

  while true do
  ...

Эта процедура тесно связана с взаимодействием с пользователем, поэтому разместим ее в модуле LowLevel:

  { ----------------- }
  procedure GenerateHero;

  begin

  end;

  {$ENDIF}

  end.

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

  { ----------------- }
  procedure GenerateHero;

  begin

    ClrScr;
    GoToXY(1,1);

  repeat
    Writeln(STR_GEN1);
    ReadLn(Heroes[CurHero].Race);
  until Heroes[CurHero].Race in [raceHuman..raceHobbit];

  repeat
    Writeln(STR_GEN2);
    ReadLn(Heroes[CurHero].Class);
  until Heroes[CurHero].Class in [classWarrior..classMage];

  Writeln(STR_GEN3);
  ReadLn(Heroes[CurHero].Name);

  end;

Запись-проверка корректности введенного пользователем значения расы и класса в нашем случае не совсем правильна. Ведь в проверке

Heroes[CurHero].Race in [raceHuman..raceHobbit]

мы основываемся на неявно заданный порядок следования констант, в котором раса человека имеет самое меньшее значение, а раса хоббита - наибольшее. Однако при изменении порядка рас, или расширении этого списка данное условие сразу станет источником ошибок. Поэтому правильный подход - это введение дополнительных констант, которые будут обозначать наименьшее и наибольшее значения рас (наподобие raceMin и raceMax). В данном контексте мы делаем достаточно условный пример с текстовым интерфейсом, поэтому подобные детали лишь отмечаем, не всегда реализовывая их явно.

Текстовые константы описаны, как и полагается, в модуле Texts:

  const
  ...

  STR_GEN1 = ' Введите расу героя: 1-человек 2-эльф 3-гном
  4-хоббит ' ;
  STR_GEN2 = ' Введите класс героя: 1-воин 2-стрелок 3-маг ' ;
  STR_GEN3 = ' Введите имя героя: ' ;

Так как в процедуре генерации персонажа GenerateHero мы очищаем содержимое экрана, в ее финальной части надо вызвать процедуру отрисовки обстановки вокруг созданного героя:

  ...
  SetHeroVisible(CurHero);
  end;

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


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

http://russianenterprisesolutions.com/sbo/download/13125.zip 10112 байтов


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

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

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


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

В избранное