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

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

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

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

Урок 18. Монстры наносят ответный удар.

Урок 18. Монстры наносят ответный удар.

 

Займемся монстром, когда он все же получил повреждение? Его здоровье проверяется, когда оно становится меньше или равным нулю, считается, что он убит и герой получит причитающийся ему за победу опыт:


Procedure HeroAttack(var H:THero; m:integer);

Var …:integer;

Begin

 

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

begin

ShowInfo(STR_BAD_ATTACK);

Exit;

End;

 

…Weapon[n]:

if … then

begin

ShowInfo(STR_NONE_WEAPONS);

Exit;

End;

 

dam   : = . WeaponDamage (   H, Slots [i]    ) ;

skin   :=  RollDice(  Monsters[m].ddl,   Monsters[m]-dd2   );

if  skin   >= dam   then

begin

ShowInfo(STR_BIG_SKIN);

Exit

end;

dec(   Monsters[m].HP,   dam-skin   );

Showlnfo(STR_ATTACK  +   IntToStr(dam-skin)    );

if Monsters[m].HP   <=   0   then

begin

Showlnfo(Monsters[m].Name   +   STR_MON_KILL);

IncXP(   H,Monsters[m].XP   );

end;

end;

 

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

 

const  STR_ATTACK =   '   Герой  наносит   повреждение   '    ;

const  STR_MON_KILL =   '   завален!    '   ;

 

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

Где будет находится процедура ответных ударов окружающих героя монстров? Она будет вызываться сразу после процедуры HeroAltack. Назовем ее MonstersAttack:

 

procedure MoveHero(   dx,dy:   Integer   );

var m,   dam:   Integer;

begin

if not  FreeTile(   GameMap[CurMap].Cells[ Heroes [CurHero] .x+dx,

Heroes [CurHero.1 .y+dy] .Tile   )   then

Exit;

m   : =  IsMonsterOnTile(Heroes[CurHero].x+dx,

Heroes[CurHero].y+dy); if m >   0   then

begin

HeroAttack(Heroes[CurHero] ,   m);

MonstersAttack;

Exit

end;

 

Отметим, что в этой процедуре мы не 01раничимся ответным ударом одного атакованного монстра. Ведь, хотя наш положительный персонаж один, нападающих па пего монстров может быть много, и каждый из них имеет право на свою атаку. При этом в свою очередь хода герой может напасть только на одного монстра, точно также, как и его противники. Каждый из них имеет право ровно на одну атаку, но ведь их несколько! Поэтому персонажу периодически придется после одного нападения отражать несколько вражеских атак. Реализуем процедуру MonstersAttack в модуле Combat.

 

procedure  MonstersAttack;

var i:   Integer;

begin

for  i   :=   1   to  MaxMonsters   do

if   (Monsters[i].HP  >   0)   and CanAttack(i,CurHero)   then

begin

MonsterAttack[I, Heroes[CurHero]);

End;

End;

 

Проверка монстра жив ли он и здоров, а также находится ли герой в зоне видимости монстра проверку вынесем в отельную функцию. Параметрами ее выступают индекс персонажа в массиве Heroes в массиве (модуле) Monsters:

 

Function CanAttack(mi, hi: Integer): Boolean;

begin

… Distance( Heroes[hi].x,Heroes[hi].y,

Monsters[mi].x,Monsters[mi].у ) = 1;

End;

 

Проверка выполняется просто - достаточно проверить, находится ли монстр на расстоянии одной клетки от персонажа. Расстояние между объектами локации измеряется, клетками по вертикали и горизонтали. Это расстояние можно вычислить с помощью … Distance

 

FunctionDistance (xf, yf, yi, xt, yt:   Integer):   Integer;

Begin

…Distance := Abs(xf-yf)   +   abs(yf-yt);

end;

 

Зрением наделен монстр, способный напасть на героя, выполняется расчет его атаки. Эта атака может быть запрограммирована так:

 

Procedure MonsterAttack (m:   Integer;   var H:   THero   );

Var  …:integer;

Begin

… (Monsters[m].Name+STR_MON_STOP);

… SkillDefence(H);

… :

Defence (Monsters[m].Adl,   Monsters[m].Ad2   );

SkillDefence(H);

If … then

begin

…(Monsters[m].Name +  STR_MON_DEF);

… :

… (Monsters[m].Name +  STR_MON_ATTACK) ;

… (H def)   ) ;

 

Вначале происходит проверка умения героя уклоняться от ударов. Умения skillDefence нет. Поэтому выполним процедуру добавления. В модуле Неrо увеличиваем значение константы MaxSkills i константу skillDefence:

 

Const …Skills=3;

Const …Weapon=1;

Const …Search=2;

ConstDefence=3;

 

Во время компиляции программы возникнет ошибка в модуле Tables - ведь мы … BaseSkill_Table, в котором храняncя базовые значения навыков. Заменим новым значением:

 

const BaseSkill__Table:. array[1. .MaxSkills] of Integer =

(

30,   20,   25

);

 

Величина 25% для защиты выглядит не очень высокой. Она означает, что герой сможет отбивать каждый четвертый удар. Однако далее мы сделаем так, чтобы со временем этот процент быстро рос - до разумных значений, конечно. Далее исправим процедуру SkillTest:

 

function  SkillTest(   var H:   THero;   ski:   Integer   ):   Boolean;

var xp:   Integer;

begin

SkillTest   :=  false;

if  random(100)+l  >  H.Skills[ski]   then 

Exit;

SkillTest   := true;

case ski  of

skillHandWeapon, skillDefence:

begin

SuccessSkillTest(H,   ski);

end;

skillTrapSearch:

begin

Showlnf о (STR__TRAPOK) ;

IncXP(H,   H.Level  +  random(H.Level));

SuccessSkillTest (H,   skillTrapSearch.) ;

end;

end;

end;

 

Здесь проверки навыков, не требующих дополнительных действий, объединены в один обработчик.

А рост навыка обороны добавим в процедуру SucccssSkillTesl. Как часто нам надо будет повышать этот навык? Вспомним аналогичные подсчеты, связанные с умением наносить удары (.skillHandWeapon).

За игру персонаж, как мы подсчитали, может атаковать монстров около двух тысяч раз. Количество ответных нападений монстров будет, конечно, большим. Ведь для героя мы считали только успешные атаки, а обороняться ему придется от всех нападений противника. Поэтому выберем приближенное значение - например, пять тысяч. Пусть навык возрастет с 25 до 75%. Большее, чем 75, значение брать неразумно - ведь тогда герой станет слишком неуязвимым и способным отражать все без исключения атаки противника. Теперь мы можем рассчитать вероятность повышения этого навыка на единицу - она будет равна 5000 / (75 - 25) или такое повышение должно происходить в одном случае из ста.

 

procedure SuccessSkillTest(  var H:   THero;   ski:   Integer);

var rnd:   Integer;

begin

case ski of

skillDefence:

begin

if random(100)   =  0 then

begin

ShowInfo(STR_DEFENCESKILL_OK) ;
            inc(H.Skills[skillDefence]);

End;

End;

 

Если герою не удалось уклониться от нападения, выполняется проверка поражения, которое наносит монстр. Эта величина зависит от характеристик монстра (поля Adl, Ad2). Наконец, вычисляется броня (величина, аналогичная шкуре монстра). Такая бронезащита связана с количеством надетой на героя брони. Расчет данного параметра производится в GetHeroDefence:

 

Function GetHeroDefence( var Н: ТНего ): Integer;

Var ..:integer;

begin

if H.Slots[SlotBody].IТуре <> itemNone then

…:=H.Slots[SlotBody].Ints[intArmorDefence];

I=d;

 

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

 

Function GetHeroDefence( var Н: ТНего ): Integer;

Var ..:integer;

begin

if H.Slots[SlotBody].IТуре <> itemNone then

D:=H.Slots[SlotBody].Ints[intArmorDefence];

if H.Slots[SlotHelm].IТуре <> itemNone then

D:=H.Slots[SlotHelm].Ints[intArmorDefence];

Defence I-d;

 

Добавим два слота шлема:

 

Const SlotBody=1;

SlotHans=2;

slotHelm=3;

 

В модуле Texts:

 

Const HeadSlots=3;

SlotName: array[1..MaxSlots]   of string[20]   =

(

  ‘ Тело’    ,    '   В   Руках   '    ,    '   На   Голове   '

);

 

В MonsterAttack  к происходит снижение уровня здоровья героя - при попадании. В упомянутых процедурах выглядят так:

STR_DEFENCESKILL_OK =   '   Вы отбили   удар!    '    ;
STR_NON_STOP='  атака   отбита!    '    ;
STR_NON_DEF=‘ наносит  удар,   но   не   пробивает   вашу’;
STR_NON_ATTACK='   наносит  удар!    '    ;


Продолжение следует...


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

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

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