Урок 21. Герой готовится к жизни
Пока что наш
герой, несмотря на способность жить в виртуальном мире и даже вести сражение,
как выражаются профессионалы ролевых игр, не сгенерирован - для него не созданы
базовые параметры (значения массива Chars),благодаря которым он будет иметь
определенную индивидуальность и отличаться от других героев в лучшую или худшую
сторону.
Процесс
генерации, создания героя, даже с точки зрения пользователя сам по себе важен и
обычно занимает немало времени. В классических системах типа AD&D этот
процесс различными способами упрощается - так, человеку предлагается выбрать
одну из предопределенных рас и один из предопределенных классов героя (воин,
лучник, маг, вор и тому подобные). Воин крепок здоровьем и хорошо дерется
ручным оружием, но плохо стреляет и совсем не способен к магии. Лучник
прекрасно стреляет, похуже сражается в ближнем бою, и также не владеет
волшебством. Маг обычно совсем хил, и в реальном бою любого вида сразу
проигрывает, зато магией владеет в совершенстве. Бывают смешанные классы -
например, паладин совмещает воина и мага. А некоторые расы более приспособлены
к определенному виду деятельности - например, эльфы мастерски стреляют из лука,
гномы хорошо дерутся в ближнем бою. А человек (игровая раса) обычно считается
потенциально равным для всех видов деятельности.
Вопрос,
вводить ли в игру понятия рас и классов, давно и яростно обсуждается
поклонниками ролевых игр. С одной стороны, такой подход существенно
ограничивает гибкость процесса генерации, с другой - вносит определенный шарм,
сразу вводит человека в игровую атмосферу, предлагая ему мыслить не конкретными
числовыми понятиями каких-то мало понятных характеристик, а уже готовыми
игровыми определениями. Будем придерживаться этой идеи и мы. Вдумчивый читатель
без труда дополнит предлагаемую нами схему реализации возможностью настраивать
те или иные параметры вручную.
Итак, нам
необходимо дополнить описание типа героя ТНего двумя новыми полями:
type
THero = record
Chars :
array[1..MaxChars] of Integer;
Skills: array[1..MaxSkills] of
Integer;
Items : array[1..MaxHeroItems] of TGameltem;
Slots : array[1..MaxSlots] of TGameltem;
x,y,
HP,
MaxHP,
Exp, MaxExp,
Level, VisLong:
Integer;
Class, Race:
Integer;
end;
Первое из
них, Class, укажет на класс героя, второе - Race - на его расу. Допустим, у нас
будет три класса - воин, лучник и маг, и четыре расы - человек (равно способный
ко всему), эльф (способный к стрельбе из лука), гном (способный к рукопашному
бою) и хоббит (способный к магии). Соответственно, подготовим константы этих
понятий в модуле Неrо:
…:=1;
…:=1;
…:=2;
…:=1;
…
Разместим
записи рас и классов, а также массивы с названиями этих понятий в модуле Texts:
…[1..MaxRace] of String[15]=
(‘ Человек ’ , ’ Эльф ’ , ’ Гном ’ , ’ Хоббит ’);
…[1..MaxClass] of string[15] =
(' Воин
', ' Стрелок '
, ' Maг ');
Можно
указывать имя героя, что сделает игру значительно более человечной. Добавим
новое поле Name длинной 20 символов:
…:record
…:array[1..MaxChars] of Integer;
…:array[1..MaxSkills] of Integer;
…:array[1..MaxHeroItems] of Integer;
…:array[1..MaxSlots] of Integer;
…:=HP;
…Long:integer;
…:integer;
…(20);
Создана
процедура, которая будет осуществлять начальное распределение всех данных расы,
класа и имени. Назовем ее GenerateHero, вызывать будем вначале игры, сразу
после процедуры инициализации героев:
…
…
взаимодействием с пользователем, поэтому разместим ее.
procedure GenerateHero;
begin
end;
{$ENDIF}
end.
В ней
человеку на выбор должны последовательно предлагаться варианты выбора расы и класса,
а затем он должен будет ввести имя своего героя. Оформим этот процесс следующим
кодом (он сильно зависит от платформы и способа взаимодействия с
пользователем):
procedure GenerateHero;
begin
ClrScr;
GoToXY(l,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(STRJ3EN3); ReadLn(Heroes[CurHero]„Name);
end;
Запись-проверка
корректности введенного пользователем значения расы и класса в нашем случае не совсем
правильна. Ведь в проверке Hcroes[CurHeroJ.Race in [raceHuman..raceHobbit] мы
основываемся на неявно заданный порядок следования констант, в котором раса человека
имеет самое меньшее значение, а раса хоббита - наибольшее. Однако при изменении
порядка рас, или расширении этого списка данное условие сразу станет источником
ошибок. Поэтому правильный подход - это введение дополнительных констант, которые
будут обозначать наименьшее и наибольшее значения рас (наподобие raceMin и
гасеМах). В данном контексте мы делаем достаточно условный пример с текстовым
интерфейсом, поэтому подобные детали лишь отмечаем, не всегда реализовывая их
явно. Текстовые константы описаны, как и полагается, в модуле Texts:
const
STR_GENl =
' Введите расу
героя: 1-человек 2-эльф
3-гном
4-хоббит ' ;
STR__GEN2 =
' Введите класс
героя: 1-воин 2-стрелок
3-маг ' ;
STR_GEN3 =
' Введите имя
героя: ' ;
Так как в процедуре
генерации персонажа GenerateHero мы очищаем содержимое экрана, в се финальной
части надо вызвать процедуру отрисовки обстановки вокруг созданного героя:
SetHeroVisible(CurHero);
end;
Следующий шаг
процесса генерации - наложение расы и класса героя на распределение его характеристик
- базовых параметров и навыков. Сделать это можно самыми разными способами.
Рассмотрим их далее.
Источник: delgame.at.ua
|