Меню сайта
Форма входа

Категории раздела
Уроки по созданию игр [38]
Программирование игр разной сложности
Игровые алгоритмы [24]
Алгоритмы, которые уже реализованы для разных жанров игр
Графика [5]
Учимся работать с графикой в Делфи
Мультимедиа [3]
Работа с мультимедийными возможностями Делфи
Другие статьи [18]
Статьи не вошедшие не в один из разделов
Ошибки [4]
Всевозможные ошибки и пути их решения
Четверг, 16.05.2024, 15:33
Приветствую Вас Гость

Статьи по программированию

Главная » Статьи » Уроки по созданию игр

Урок 26. Первые заклинания

Урок 26. Первые заклинания

 

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

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

Воспользуемся вторым подходом. Добавим в список навыков новый skillThrovvSpell, не надо править константы skillMax и MaxSkills:

 

Const

SkillMin=l ;

SkillHandWeapon=1;

SkillTrapSearch = 2;

SkillDefence=3;

SkillRangedWeapon=4;

SkillThrowSpell   =   5;

SkillMax=5;

Const

SkillIn=5;

SkillName:array[1..MaxSkills]   of  string[20]   =

(

'Ручное оружие', 'Поиск  оружия' , 'Защита', 'Стрельба из лука' , 'Бросок   заклинания'

);

 

Компилятор подскажет нам, какие строки кода нуждаются в дополнении:

 

Const BaseSkill_Table:   array[1..MaxSkills]   of   Integer  =

(

5, 10, 25,   30,    40

);

Const BaseSkill_Table:array[SkillMin. . skillMax,   classWarrior. . classMage,    1..2   ] of integer=

(

((30,15), (50,20), (25,10) ) ,

((20,20), (30,15), (60,20)),

((20,20), (50,20), (15,10)),

((20,20), (80,20), (35,20)),

((0,0),(20,20),(45,25))

);

 

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

Метание заклинания будем осуществлять по нажатию на клавишу 't': |

 

Case t of

t:

…:=SkillThrowSpell;

End;

 

Созадим отдельный модуль, назовем его Magik:


implementation

end.

 

В нем и разместим заголовок и реализацию процедуры ThrowSpell. Она должна прежде всего проверить соответствующий навык:

 

interface

procedure ThrowSpell;

implementation uses Hero, LowLevel, Texts;

{           }

procedure ThrowSpell;

begin

if not SkillTest(Heroes[CurHero], skillThrowSpell) then

begin

ShowInfo(STR_MAGIK_BADTEST);

Exit

end;

 

Тут мы использовали текстовую константу (размещаем ее, как обычно, в Texts):

 

STR_MAGIK_BADTEST =   '   Попытка броска  заклинания неудачна.    '   ;

 

Расширим процедуру SkillTest новым навыком:

 

case  ski   of

skillHandWeapon, skillRangedWeapon, skillThrowSpell, skillDefence:

begin

SuccessSkillTest(H,   ski);

end;

Добавим код увеличения навыка в процедуру SuccessSkillTest: skillThrowSpell:

begin

if  random(50)   =   0   then

begin

Showlnfo(STR_THROWSPELLSKILL_OK);

inc(H.Skills[skillThrowSpell]);

end;

end;

 

Текстовая константа:

 

STR_THROWSPELLSKILL_OK =   '   Навык заклинаний  повышен! ' ;

 

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

 

const

MaxSpelllnt =  10;

type  TSpell   =  record

Name:   String[30];

Mana:   Integer;

ints:   array [1. ..MaxSpelllnt ]   of  Integer;     

end;

 

Сразу подготовим массив-константу описаний типов заклинаний (по аналогии с массивом описаний типов предметов):

 

Const Spells:   array[1..MaxSpells]   of  TSpell  =

(

Name:STR_SPL_FIRESTORM;   Mana:3;   Ints : (0, 0, 0, 0, 0, 0, 0, 0, 0, 0) ) ,

Name:STR_SPL_SELFHEALING;   Mana:l;    Ints:(0,0,0,0,0,0,0,0,0,0)

);

Константы

MaxSpells=2;

STR_SPL_FIRESTORM=   '   Огненный Шторм   '    ;

STR_SPL_SELFHEALING=   '   СамоИсцеление   '   ;

(размещаем в модуле Texts)

 

Следующий шаг - создание интерфейсной функции, которая будет запрашивать необходимое заклинание. Пусть она вернет номер заклинания в массиве Spells или 0, ecли оно не выбрано. Назовем эту функцию GetSpellNo, а разместим ее в модуле LowLcvel.


            GetSpellNo:    Integer;

Var i:integer;

Begin

ClrSCR;

GoToXY (1,2) ;

For i:=1 to MaxSpells do

WriteLn(i,    '    )    '    , Spells [i] .Name,    '    :    '    , Spells [i] .Mana) ;

Writeln(STR_SPL_GETNUM) ;

Readln(i);

GetSpellNo:=0;

End;

If not ()  in   [1..MaxSpells])   then

Exit;

GetSpellNo:=i;

End;

 

Текстовая константа:

 

GetSpellNUM =   '   Введите   номер  функции или  0:';

 

Еще необходимо проверить, достаточно ли у героя маны:


           

procedure ThrowSpell;

var n:integer;

begin

n:=GetSpellNo;

if n=0 then  Exit;

if Heroes[CurHero] .Mana  <   Spells[n] .Mana   then

begin

ShowInfo(STR_MAGIK_BADMANA) ;

Exit;

End;

…(Heroes[CurHero] .Mana,   Spells[n].Mana);

           

Текстовая константа:

 

STR_MAGIK_BADMANA =   '   Недостаточно маны!';

           

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

Наконец, наступает процесс реализации самих заклинаний. Подготовим для этого оператор выбора (в нем используются две новые константы-индексы заклинаний в массиве Spells):

 

const

splFireStorm = 1; splSelfHealing = 2;

case n of

splFireStorm:

begin

end;

splSelfHealing:

begin

end;

end;

 

Как будет работать огненный шторм? Надо перебрать все окружающие героя клетки, проверить, сеть ли на них монстры, и нанести каждому некоторое поражение. Напомним, что у нас есть удобная процедура HeroAltackFin, которая учитывает воздействие заданной величины поражения на монстра. Только ее заголовок надо записать в интерфейсном разделе модуля Combat, и подключить сам модуль в раздел реализации Magik. Кроме того, после атаки монстров надо передать им ход - вызвать процедуру MonslersStep. Только делать это надо не каждый раз после удара по конкретному монстру, а после обработки всех попавших под атаку монстров. Кроме того, если ни один монстр под влияние огненного шторма не попал, ответный ход противника не нужен.

Для реализации такого алгоритма добавим локальную переменную-флажок Г, которая будет принимать true, когда какой-нибудь монстр попадет под удар:

 

splFireStorm:

begin

f   :=   false;

for x := Heroes[CurHero].x-1 to Heroes[CurHero].x+1 do

for у := Heroes[CurHero].y-1 to Heroes[CurHero].y+1 do

begin

n := IsMonsterOnTile(x,y); if n > 0 then

begin

dam := random(4)+1;

HeroAttackFin(Heroes[CurHero],n,dam);

f   :=  true;

end;

end;

if   f  then

MonstersStep;

end;

 

Механизм исцеления пусть работает так. Герой теряет одну единицу маны, и восстанавливает одну единицу здоровья. При этом данное заклинание злости у монстров не вызовет, то есть его можно будет выполнять сколько угодно раз подряд (сколько позволит мана), не опасаясь атаки стоящих рядом врагов.

 

splSelfHealing:

begin

dec(Heroes[CurHero].Mana); IncHP(Heroes[CurHero],    +1);

ShowInfo(STR_SPL_SELFHEALING) ;        .           '.

End;

 

Текстовая константа:

 

STR_SPL_SELFHEALING =   'Самоисцеление успешно!';

 

Связавшись с доступными на данный момент классами, можно заметить один момент, который стал особо явным после создания персонажа-мага: ману постоянно нужно восстанавливать, да и здоровье тоже неплохо было бы увеличивать также каким-то искусственным путем, а не только через источники. Кстати, в источниках нам надо и «с иосстановление маны, а сделать это совсем просто:

 

If GameMap[CurMap] .Cells[

Heroes[ CurHero] .х, Heroes [Cur Her о] .у] .Tile   in

If ..TileSet    then

BEGIN

ShowInfo(STR_ LIVE);

IncHp(Heroes[CurHero],   Heroes[CurHero].MaxHP  );

IncMana(Heroes[CurHero] ,   Heroes [CurHero] .MaxMana   ) ;

 

(… расширенный вызовом IncMana в процедуре MoveHero модуля Game).

Сама процедура IncMana (увеличение уровня маны героя) запишется в модуле Неrо:

             

Procedure IncMana (  var H:   THero;   mad:   Integer   );

begin

H.Mana:=H. Mana   + mad;

If H.Mana-H.MaxMana then H.Mana := H.MaxMana;

End;

 

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

Далее перейдем к работе с Магическими предметами.


Источник: delgame.at.ua

Категория: Уроки по созданию игр | Добавил: Armageddets (04.03.2014) | Автор: Урок 26. Первые заклинания
Просмотров: 985 | Теги: игра на делфи, магия персонажа, программирование delphi, Первые заклинания | Рейтинг: 0.0/0
Всего комментариев: 0
Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]
Наш опрос
Какие уроки по созданию игр Вам удобнее?
Всего ответов: 141
Мини-чат
Друзья сайта
  • Официальный блог
  • Сообщество uCoz
  • FAQ по системе
  • Инструкции для uCoz
  • Статистика

    Онлайн всего: 1
    Гостей: 1
    Пользователей: 0