Драки с монстрами
Last updated
Last updated
Итак, для начала создадим два новых демона для атак в level.py
:
Думаю, по названиям понятно, что демоны нужны для обозначения процесса атаки. Дополним метод вызова врагов помимо видимых спрайтов, атакуемыми спрайтами (self.attack_sprites
):
Также, дополним метод create_attack
атакующим спрайтом (self.attack_sprites
) :
Далее пропишем новый метод с логикой атаки игрока:
Самая интересная строка тут, это строка с методом пайгейма pygame.sprite.spritecollide
. Данный метод позволяет удалять спрайт из группы. Первый аргумент функции — спрайты для атаки, второй — группа спрайтов, из которой мы будем удалять спрайт, третий — DoKill. Если у DoKill установлено значение True
, все спрайты, которые сталкиваются, будут удалены из группы. Далее, в run-методе пропишем наш метод. Исход:
Немного улучшим метод player_attack_logic
:
Мы стали сопоставлять наши спрайты по типам. В моём проекте типов только два (enemy и weapon). Я прописал в файле weapon.py
в демоне строку для присваивания ему нового типа:
Далее нам не нужно удалять врага при ударе. Нам нужно прописывать ему урон от нашего оружия. Собственно, теперь нужно в файле enemy.py прописать новый метод — get_damage
:
Тут мы прописываем новый метод (get_full_weapon_damage
), который должен высчитывать сумму урона от оружия и от силы самого Линка (прямо как в Dark Souls). Пропишем же данный метод в player.py
:
Находим и складываем уроны из наших списков. Возможно, тут встанет вопрос: "Зачем так сложно, если у нас только один меч и всё?". Я хотел бы сделать проект так, чтобы вы могли самостоятельно с ним "поиграться". Собственно и цель книги не номинация "Игра года" в The Game Awards, а лишь попытка продемонстрировать работоспособность языка Python как неплохого движка. Ну да вернёмся к коду. Помимо урона, я решил сразу прописать кулдаун оружия и заменил строку:
На строку:
Напишем новый метод в enemy.py
на проверку смерти монстра:
Тут я даже не знаю что ещё подсветить в коде :) Не забудьте добавить данный метод в update-метод. Теперь один удар приводит к смерти врага. Таким образом, PyGame считает, что пока оружие соприкасается с врагом (вызывается метод коллизий), удары наносятся один за другим. Как итог — Линк танк, который уничтожает всё на своём пути. Исправим это. Для начала, создадим новых демонов enemy.py
:
Тут достаточно прозрачные демоны. Важный момент — флаг уязвимости. Если он поднят — враг может получать урон. Теперь встроим их в get_damage
:
Далее необходимо дополнить код cooldown-метода:
Тут, как я говорил ранее, сразу добавляем вариацию флага. У нас было место, где флаг опускается и теперь в cooldown-методе он поднимается по истечению указанного времени неуязвимости. Теперь все враги убиваются весьма приятно. Теперь, нужно добавить отбивание врага на дистанцию, которая указана у каждого врага. Создадим ещё метод:
Осталось вычислить положение в методе get_damage
:
Теперь добавим мерцание во время удара, чтобы понять что удар был сделан. В PyGame все сигнатуры (синусоидные функции) лежат в диапазоне от -255 до 255, а позиции удобно брать из синусоид, так как интерпретация в Python будет работать на основе степеней (как и любой калькулятор), а затем будет процесс получения точки на синусоиде. Этот процесс я описывал дольше, чем будет писаться метод отображения пульсации:
Данный метод написан в entity.py
. Не забудьте импортировать sin-метод из библиотеки math. Теперь вызовем данный метод при ударе по врагу в методе animate
:
Сейчас мы бьём врагов абсолютно верно и можем отследить когда монстры атакуют нас (в терминал приходит сообщение "attack"). Осталось сделать метод, который делает урон Линку. Пропишем его в level.py
:
Дополним в create_map
в строку вызова монстров нанесение урона Линку:
Добавим в Enemy-класс параметр (damage_player
) и пропишем нового демона — self.damage_player = damage_player
. Теперь вместо простого вывода сообщения "attack" выполним вызов нашего метода:
Добавим параметры таймеров в демонов нашего player-класса:
Они аналогичны демонам в enemy.py
. Далее традиционно пропишем смену флага в наш кулдаун-метод:
Теперь пропишем наше мерцание. Тут всё также, как и ранее. Прописывать будем в animate-методе:
Теперь нам нужно восстанавливать энергию (повторим механику из Dark Souls). Для этого создадим метод energy_recover
:
Далее пропишем, что при ударе у нас теряется 10 очков стамины, а если её не хватает — атака не проходит:
Последнее, что я хотел бы сделать — добавить экспу за убийство врага в level.py
:
Добавим этот же метод для create_map
в Enemy
. Далее повторим всё, что делали ранее с damage_player
.
. Приступим к последнему шагу — музыке.