Усиления и коллекционные предметы в Python Arcade

Создайте простую игру
Начните с минимального набора: игрок, который может передвигаться в четырёх направлениях (влево, вправо, вверх, вниз) с помощью клавиатуры, и один объект-враг для взаимодействия. Ниже — полная исходная версия файла simple-game.py.
Код, используемый в статье, доступен в репозитории на GitHub и распространяется под лицензией MIT.
Создайте новый файл с именем simple-game.py и добавьте код ниже:
import arcade
blue = arcade.color.BLUE
red = arcade.color.RED
black = arcade.color.BLACK
white = arcade.color.WHITE
yellow = arcade.color.YELLOW
green = arcade.color.GREEN
orange = arcade.color.ORANGE
class Game(arcade.Window):
def __init__(self, width, height):
super().__init__(width, height)
arcade.set_background_color(black)
self.player = arcade.SpriteCircle(20, blue)
self.player.center_x = width // 2
self.player.center_y = height // 2
self.enemy = arcade.SpriteSolidColor(20, 20, red)
self.enemy.center_x = width // 4
self.enemy.center_y = height // 4
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 -= 10
elif key == arcade.key.RIGHT:
self.player.center_x += 10
elif key == arcade.key.UP:
self.player.center_y += 10
elif key == arcade.key.DOWN:
self.player.center_y -= 10
def main():
game = Game(800, 600)
arcade.run()
if __name__ == "__main__":
main()Запустите этот код, и у вас будет простая сцена с игроком и врагом. Это базовый каркас, на который будут навешиваться остальные механики.
Состояния игры: счёт и здоровье
Для реализации пауэр-апов и коллекционных предметов понадобятся состояния игры: счёт (score) и здоровье (health). Обрабатывайте их через отдельные поля класса. При столкновении с врагом здоровье будет уменьшаться.
Добавьте в класс Game следующие фрагменты кода:
class Game(arcade.Window):
def __init__(self, width, height):
super().__init__(width, height)
self.score = 0
self.health = 100
def on_draw(self):
arcade.draw_text(f"Score: {self.score}", 10, 10, white)
arcade.draw_text(f"Health: {self.health}", 10, 30, white)
def update(self, delta_time):
if arcade.check_for_collision(self.player, self.enemy):
self.health -= 10
if self.health <= 0:
self.game_over()
def game_over(self):
# Add game over logic here
passТеперь при столкновении здоровье уменьшается на 10 единиц. Значения счёта и здоровья отображаются на экране.
Добавление коллекционных предметов
Коллекционные предметы увеличивают счёт. В примере — +10 очков за предмет. Для разнообразия формы и внешнего вида используйте разные спрайты.
Создайте новый файл collectibles.py или добавьте в Game:
class Game(arcade.Window):
def __init__(self, width, height):
super().__init__(width, height)
self.collectibles = arcade.SpriteList()
for _ in range(5):
collectible = arcade.SpriteSolidColor(20, 40, yellow)
collectible.center_x = random.randint(0, width)
collectible.center_y = random.randint(0, height)
self.collectibles.append(collectible)
def on_draw(self):
arcade.start_render()
self.player.draw()
self.enemy.draw()
self.collectibles.draw()
arcade.draw_text(f"Score: {self.score}", 10, 10, white)
arcade.draw_text(f"Health: {self.health}", 10, 30, white)
def update(self, delta_time):
for collectible in self.collectibles:
if arcade.check_for_collision(self.player, collectible):
self.score += 10
collectible.remove_from_sprite_lists()В этом примере создаётся список из 5 коллекционных предметов жёлтого цвета. При сборе предмета счёт увеличивается.
Добавление усилений
Усиления (power-ups) дают временные способности. В примере — щит, который активируется на 10 секунд. Во время действия щита при столкновении с врагом враг уничтожается.
Добавьте в Game блок кода ниже:
class Game(arcade.Window):
def __init__(self, width, height):
super().__init__(width, height)
self.power_up = arcade.SpriteSolidColor(50, 20, green)
self.power_up.center_x = random.randint(0, width)
self.power_up.center_y = random.randint(0, height)
self.shield_active = False
self.shield_duration = 10
self.shield_timer = 0
def on_draw(self):
arcade.start_render()
self.player.draw()
self.enemy.draw()
self.collectibles.draw()
self.power_up.draw()
arcade.draw_text(f"Score: {self.score}", 10, 10, white)
arcade.draw_text(f"Health: {self.health}", 10, 30, white)
def update(self, delta_time):
if arcade.check_for_collision(self.player, self.enemy):
if not self.shield_active:
self.health -= 10
if self.health <= 0:
self.game_over()
else:
self.enemy.remove_from_sprite_lists()
if self.shield_active:
self.shield_timer += delta_time
if self.shield_timer >= self.shield_duration:
self.shield_active = False
self.shield_timer = 0
for collectible in self.collectibles:
if arcade.check_for_collision(self.player, collectible):
self.score += 10
collectible.remove_from_sprite_lists()
if arcade.check_for_collision(self.player, self.power_up):
self.shield_active = True
self.power_up.remove_from_sprite_lists()Вы получите поведение щита: он активируется при подборе, действует заданное время и затем отключается. Во время действия щита игрок уничтожает врага при столкновении.
Дополнительные усиления: таймер
Ещё один тип усиления — продление игрового времени. В примере таймер даёт +10 секунд к оставшемуся времени.
Добавьте файл timer-power-up.py или расширьте Game следующим кодом:
class Game(arcade.Window):
def __init__(self, width, height):
super().__init__(width, height)
arcade.set_background_color(black)
self.player = arcade.SpriteCircle(20, blue)
# ...
self.timer_power_up = arcade.SpriteSolidColor(40, 20, orange)
self.timer_power_up.center_x = random.randint(0, width)
self.timer_power_up.center_y = random.randint(0, height)
self.game_time = 60# Initial game time in seconds
self.timer_power_up_duration = 10
# ...
def update(self, delta_time):
# ...
if arcade.check_for_collision(self.player, self.timer_power_up):
self.game_time += self.timer_power_up_duration
self.timer_power_up.remove_from_sprite_lists()
# ...
def main():
game = Game(800, 600)
arcade.run()
if __name__ == "__main__":
main()Такие усиления помогают управлять темпом игры и дают игроку дополнительную цель — найти таймер.
Лучшие практики для усилений и коллекционных предметов
Ниже — подробнее про дизайн, баланс и обратную связь. Эти рекомендации пригодятся как инди-разработчикам, так и тимлидам.
Визуальная ясность и согласованность
- Используйте чёткие иконки и цвета, чтобы предметы выделялись на фоне уровня.
- Связывайте визуал с эффектом: щит — синий контур, таймер — часы или оранжевый таймер.
- Сохраняйте единый стиль для всех предметов, чтобы игрок мог быстро распознавать их значение.
Баланс и сложность
- Контролируйте редкость предметов: редкие предметы должны давать заметный бонус.
- Не перегружайте игрока — избыток усилений снижает значимость решения о сборе.
- Давайте длительности усилений и их силе логическое соотношение: мощные усиления — короткая длительность.
Ясные индикаторы и обратная связь
- Показывайте визуальные эффекты при подборе: частицы, пульсация, краткая анимация.
- Добавьте звуковой эффект, чтобы игрок сразу понял, что произошло.
- Для временных эффектов показывайте таймер на HUD.
Соотношение вызова и награды
- Препятствия и задачи, ведущие к усилению, должны соответствовать его ценности.
- Сложные или рискованные маршруты пусть дают более ценные предметы.
Плейтестинг и балансировка
- Проводите регулярные сеансы тестирования с разными группами игроков.
- Смотри на то, как часто предметы подбираются и как они влияют на окончательный результат.
- Изменяйте параметры через конфиги, чтобы быстро тестировать варианты.
Когда это не работает
- Если усиления слишком часты, игроки перестанут их ценить.
- Если усиления слишком мощные и продолжаются долго, игра теряет вызов.
- Если визуал предметов не читается — игроки будут игнорировать объекты.
Важно: если взаимодействия предметов и врагов создают непредвиденные комбинации, добавьте ограничения (например, только одно активное усиление одновременно).
Альтернативные подходы
- Система очков опыта и апгрейдов: вместо временных бонусов давайте постоянные улучшения после накопления очков.
- Модификаторы уровня: разместите усиления в труднодоступных местах и делайте их частью уровня, а не случайного спавна.
- Система карточек: игрок подбирает карточки с эффектом, а активирует их вручную.
Ментальные модели и эвристики
- «Риск–Награда»: чем выше риск получить усиление, тем более ценный должен быть бонус.
- «Ограниченный инвентарь»: ограничение по числу усилений заставляет выбирать стратегию.
- «Комбинация эффектов»: думайте о том, какие усиления сочетаются, а какие конфликтуют.
Факт-бокс: ключевые параметры из примеров
- Уменьшение здоровья при столкновении: 10 единиц.
- Начальное здоровье игрока: 100 единиц.
- Коллекционные предметы дают: +10 очков.
- Длительность щита: 10 секунд.
- Базовое игровое время в примере: 60 секунд.
Эти числа взяты из примеров кода и служат отправной точкой для баланса.
Мини-методология внедрения усилений и коллекций
- Определите список усилений и их назначение (атака, защита, время, скорость).
- Сделайте минимальные прототипы для каждого усиления.
- Добавьте визуальные и звуковые сигналы для каждого эффекта.
- Настройте параметры (длительность, сила, частота появления) через конфиг.
- Проведите серию A/B тестов и соберите данные плейтестов.
- Итеративно отбалансируйте и повторите.
Чек-лист по ролям
Разработчик:
- Реализовать спавн предметов через SpriteList.
- Обеспечить удаление предметов после подбора.
- Добавить таймеры для временных эффектов.
Художник:
- Подготовить читаемые иконки/спрайты для предметов.
- Обеспечить контраст и размер, который видно на любом разрешении.
QA:
- Проверить, что предметы не застревают в коллайдерах.
- Проверить, что эффекты отключаются по таймеру.
- Проверить сценарии множественного подбора.
PROD/PM:
- Проверить задействованные метрики: частота подбора, влияние на среднюю продолжительность игры.
- Определить, нужно ли изменять редкость или силу.
Критерии приёмки
- Усиление визуально заметно и имеет звук при подборе.
- Эффект активируется корректно и отключается по таймеру.
- Коллекционные предметы корректно увеличивают счёт и удаляются.
- Нет утечек памяти из-за неочищенных списков спрайтов.
Тест-кейсы и критерии приёмки
- Подбор щита: игрок касается спрайта щита — щит активируется, враг уничтожается при столкновении в течение 10 секунд.
- Истечение таймера: после 10 секунд щит отключается и враг снова наносит урон.
- Коллекционные предметы: счёт увеличивается на 10 и предмет исчезает.
- Множественный подбор: если два предмета подбираются почти одновременно, оба корректно обрабатываются или применяется правило «одно усиление одновременно», в зависимости от решения.
- Границы экрана: предметы не спавнятся за пределами видимой области.
Совместимость и миграция
- Проверьте API вашей версии Arcade: имена классов SpriteList, SpriteSolidColor и методы коллизии могут отличаться в разных версиях.
- Разделяйте игровую логику и визуальные ресурсы, чтобы проще мигрировать спрайты и эффекты.
Безопасность и производительность
- Ограничивайте количество одновременно активных частиц и анимаций.
- Используйте SpriteList для массовых отрисовок — это существенно быстрее.
- Удаляйте объекты из списков, чтобы избежать накопления неиспользуемых спрайтов.
Шаблон плейбука внедрения (SOP)
- Создать ветку feature/powerups.
- Добавить минимальный прототип в игровой цикл.
- Подключить спрайты и HUD-индикаторы.
- Написать модульные тесты для логики включения/выключения эффектов.
- Провести плейтесты с 10–20 игроками.
- Внести корректировки по результатам плейтестов.
- Смерджить в основную ветку и закрыть задачу.
Заключение
Усиления и коллекционные предметы — мощный инструмент дизайна, который может изменить ритм игры, усилить мотивацию игрока и добавить глубину стратегии. Начните с простых примеров: счёт, здоровье, коллекты, щит и таймер. Затем итеративно тестируйте и балансируйте. Помните о визуальной ясности, аудио-обратной связи и производительности.
Важно: экспериментируйте, собирайте данные плейтестов и корректируйте редкость и мощь усилений, пока не получите желаемый игровой опыт.
Итог: внедрение усилений и коллекционных предметов в Python Arcade — это сочетание программной реализации и дисциплины игрового дизайна. Используйте предложенные шаблоны и чек-листы, чтобы ускорить разработку и минимизировать ошибки.