Реализуем систему здоровья в Arcade (Python)
Введение
Добавление системы здоровья в аркадную игру повышает вовлечённость игрока и создаёт дополнительный слой риска и стратегии. В материале показано простое и понятное решение на Python + Arcade, пригодное для обучения и быстрого прототипирования.
Важно: код примеров сохранён как рабочий — его можно сразу запустить и адаптировать.
Что вы получите (варианты запроса)
- Как реализовать шкалу здоровья и её визуализацию
- Как обрабатывать урон и лечение
- Как добавить усиления (power-ups) и разные типы врагов
- Как сделать систему модульной и протестировать её
Начало: простая игра
Установите библиотеку Arcade:
pip install arcadeСоздайте простой игровой файл. Ниже — исходный код из исходной статьи. Скопируйте его в файл с именем simple-game.py и запустите.
import arcade
# Set window dimensions
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
# Set player movement speed
PLAYER_MOVEMENT_SPEED = 5
white = arcade.color.WHITE
blue = arcade.color.BLUE
red = arcade.color.RED
class GameWindow(arcade.Window):
def __init__(self, width, height):
super().__init__(width, height)
arcade.set_background_color(white)
# Create player and enemy objects
self.player = arcade.SpriteCircle(30, blue)
self.enemy = arcade.SpriteCircle(30, red)
self.player.center_x = 100
self.player.center_y = 100
self.enemy.center_x = 400
self.enemy.center_y = 300
def on_draw(self):
arcade.start_render()
self.player.draw()
self.enemy.draw()
def update(self, delta_time):
pass
def on_key_press(self, key, modifiers):
if key == arcade.key.LEFT:
self.player.center_x -= PLAYER_MOVEMENT_SPEED
elif key == arcade.key.RIGHT:
self.player.center_x += PLAYER_MOVEMENT_SPEED
elif key == arcade.key.UP:
self.player.center_y += PLAYER_MOVEMENT_SPEED
elif key == arcade.key.DOWN:
self.player.center_y -= PLAYER_MOVEMENT_SPEED
def main():
game = GameWindow(SCREEN_WIDTH, SCREEN_HEIGHT)
arcade.run()
if __name__ == "__main__":
main()После запуска вы увидите окно с двумя кругами — игроком (синий) и врагом (красный):

Переменные и константы для здоровья
Добавим базовые переменные, которые будут отслеживать текущее здоровье игрока, скорость восстановления и таймер лечения. Вставьте эти поля в конструктор класса GameWindow.
class GameWindow(arcade.Window):
def __init__(self, width, height):
# ...
# Health-related variables and constants
self.player_health = 100
# Health points healed per second
self.heal_rate = 1
# Timer for healing
self.heal_timer = 0
def update(self, delta_time):
# ...
# Update healing timer
self.heal_timer += delta_time
# Heal the player's health every 2 seconds
if self.heal_timer >= 2:
self.player_health += self.heal_rate
self.heal_timer = 0
# Ensure health doesn't exceed the maximum value
if self.player_health > 100:
self.player_health = 100Пояснение: heal_rate — сколько единиц здоровья восстанавливается каждые 2 секунды. heal_timer накапливает delta_time между кадрами.
Урон и лечение: столкновения
Чтобы отнимать здоровье при столкновении игрока и врага, используйте check_for_collision. Добавьте соответствующую логику в метод update.
class GameWindow(arcade.Window):
def __init__(self, width, height):
# ...
def update(self, delta_time):
# Detect collisions between player and enemy
if arcade.check_for_collision(self.player, self.enemy):
self.player_health -= 5
# ...Совет: используйте интервалы времени или «временную невосприимчивость» (invincibility frames), чтобы здоровье не пропадало слишком быстро при длительном перекрытии спрайтов.
Пример: храните last_hit_timer и не наносите урон, пока он меньше порога.
Смерть игрока и завершение игры
Когда здоровье достигает нуля или ниже, считаете игрока погибшим и завершаете игру. Добавьте проверку в update.
class GameWindow(arcade.Window):
def __init__(self, width, height):
# ...
def update(self, delta_time):
# ...
# Check if player health is zero or below
if self.player_health <= 0:
# End the game
arcade.close_window()
# ...Важно: вместо немедленного закрытия окна вы можете переключаться на экран «Game Over», предлагать рестарт или сохранять статистику игрока.
Визуализация: бар здоровья
Добавим визуальный бар здоровья — простой и эффективный индикатор состояния игрока. Вставьте код в метод on_draw.
class GameWindow(arcade.Window):
def __init__(self, width, height):
# ...
def on_draw(self):
arcade.start_render()
self.player.draw()
self.enemy.draw()
gray = arcade.color.LIGHT_GRAY
green = arcade.color.GREEN
# Draw health bar
arcade.draw_rectangle_filled(SCREEN_WIDTH // 2, 20,
SCREEN_WIDTH, 20, gray)
health_width = self.player_health / 100 * SCREEN_WIDTH
arcade.draw_rectangle_filled(health_width // 2, 20,
health_width, 20, green)Результат визуализации (пример):
Совет по UX: размещайте бар в месте, где он не заслоняет игровое поле, и используйте подсказки (цвета, мерцание) при критическом здоровье.
Дополнительные функции
Ниже — идеи и примеры кода для расширения системы.
Числовой индикатор здоровья
Чтобы показать точное значение, отрисуйте текст рядом с баром.
# Inside the on_draw() method
black = arcade.color.BLACK
text = f"Health: {self.player_health}"
arcade.draw_text(text, 10, 10, black, 14)Локализованный вариант (русский UI):
# Русский текст для интерфейса
black = arcade.color.BLACK
text = f"Здоровье: {self.player_health}"
arcade.draw_text(text, 10, 10, black, 14)Усиления здоровья (power-ups)
Добавьте объекты-усиления, которые увеличивают здоровье при столкновении:
# Inside the update() method
if arcade.check_for_collision(self.player, self.power_up):
self.player_health += 20
# Remove the power-up from the game
self.power_up.kill()Разные типы врагов
Различные враги наносят разный урон — это простая механика для усложнения уровней:
# Inside the update() method
if arcade.check_for_collision(self.player, self.enemy):
if self.enemy.type == "weak":
self.player_health -= 5
elif self.enemy.type == "strong":
self.player_health -= 20Архитектура: как сделать систему модульной
Рекомендуется вынести систему здоровья в отдельный класс или компонент. Это упростит тестирование и повторное использование.
Пример класса HealthComponent (микро-реализация):
class HealthComponent:
def __init__(self, max_health=100, heal_rate=1, heal_interval=2.0):
self.max_health = max_health
self.current = max_health
self.heal_rate = heal_rate
self.heal_interval = heal_interval
self._timer = 0.0
self._invulnerable_timer = 0.0
def update(self, delta):
self._timer += delta
if self._timer >= self.heal_interval:
self.current = min(self.max_health, self.current + self.heal_rate)
self._timer = 0.0
if self._invulnerable_timer > 0:
self._invulnerable_timer -= delta
def take_damage(self, amount, invulnerable_time=0.5):
if self._invulnerable_timer > 0:
return False
self.current = max(0, self.current - amount)
self._invulnerable_timer = invulnerable_time
return True
def heal(self, amount):
self.current = min(self.max_health, self.current + amount)
def is_dead(self):
return self.current <= 0Интеграция: создавайте экземпляр HealthComponent в GameWindow и делегируйте обновления/урон/лечение ему.
Тестирование и критерии приёмки
Критерии приёмки
- Игрок начинает с заданного максимума здоровья.
- При столкновении с «слабым» врагом здоровье уменьшается на 5, со «сильным» — на 20.
- Полоса здоровья отображает текущий процент корректно.
- При достижении 0 здоровье игра переходит в экран Game Over или окно закрывается.
- Лечение происходит автоматически по таймеру и не превышает максимум.
Примеры тест-кейсов
- Unit-test HealthComponent.take_damage(): наносим урон 10 — ожидаем уменьшение на 10.
- Unit-test invulnerability: два удара подряд с малого интервала — второй удар игнорируется.
- UI-test: при current = 50 ширина полосы равна SCREEN_WIDTH * 0.5.
- Integration: подбирать частоту кадров (delta_time) и симулировать 5 секунд — проверять накопление лечения.
Рекомендации и лучшие практики
Важно:
- Делайте систему модульной — отделяйте логику от представления (визуализации).
- Валидируйте входные значения: не позволяйте current выйти за диапазон [0, max_health].
- Добавьте тесты для граничных случаев: 0, max, переполнение, отрицательные значения.
- Предусмотрите события: on_death, on_heal, on_damage — это упростит интеграцию со звуком и анимацией.
Примечание: аудио и визуальные сигналы важны — предупредите игрока о критическом состоянии.
Альтернативные подходы и модели
- «Щит + HP»: разделите здоровье на щит (восстанавливаемый) и жизненные очки (не восстанавливаются автоматически).
- «Система ранений»: вместо числового HP используйте уровни состояния (здоров, ранен, критичен), влияющие на управление.
- «Сердечки»: классический визуальный подход с дискретными единицами (например, 5 сердечек вместо 100 очков).
Когда этот подход не подходит
- Для игр, где каждая ошибка должна быть фатальной (roguelike с перманентной смертью), нужно проектировать систему иначе.
- В многопользовательных играх важно синхронизировать состояние здоровья через сервер и учитывать лагающие обновления.
Безопасность и сохранение состояния
- При сохранении состояния сохраните не только текущее здоровье, но и таймеры (heal_timer, invulnerable_timer), чтобы при загрузке поведение оставалось предсказуемым.
- В сетевых играх авторитет сервера должен подтверждать урон во избежание читерства.
Быстрый чек-лист для релиза
- Модуль здоровья покрыт unit-тестами
- Нулевая и максимальная границы проверены
- События on_death/on_heal реализованы
- UI-чувствительность (цвет, мерцание) протестирована на разных разрешениях
- Сохранение и загрузка здоровья корректно работают
Decision flow (упрощённая логика)
flowchart TD
A[Игрок инициализирован] --> B{Столкновение с врагом?}
B -- Да --> C[Попытка нанести урон]
C --> D{Инвulnerable?}
D -- Нет --> E[Уменьшить здоровье]
D -- Да --> F[Игнорировать урон]
B -- Нет --> G{Проходит время для лечения?}
G -- Да --> H[Восстановить здоровье]
G -- Нет --> I[Обычный апдейт]
E --> J{Здоровье <= 0?}
J -- Да --> K[Game Over]
J -- Нет --> IЗаключение
Добавление системы здоровья — относительно простая, но мощная механика для аркадной игры. Главное — сделать её понятной игроку, модульной в коде и протестированной на граничных сценариях. Вы можете начать с базовой реализации, а затем расширять систему: добавлять усиления, разные классы врагов, щиты и эффектные визуальные подсказки.
Краткое резюме:
- Выясните требования: дискретное или непрерывное здоровье.
- Выделяйте логику в отдельные компоненты.
- Тестируйте и защищайте от некорректных значений.
- Думайте про UX: цвет, текст и звук делают систему понятной.
Важно: начните с простого прототипа, затем итеративно улучшайте механику и UX.
Похожие материалы
Запретить изменение фона рабочего стола в Windows
Установка Anaconda на Ubuntu — руководство
Ошибка 0x80d03801 в Microsoft Store — устранение
Таймер сна в Deezer — как включить и настроить
Защита устаревших устройств без обновлений