Механики прыжков в платформере на Python с Arcade

Прыжковая механика — одна из ключевых составляющих платформера. Она определяет ощущение игры: отзывчивость управления, темп прохождения и возможности дизайна уровней. Библиотека Arcade даёт простой и понятный API для реализации таких механик на Python.
Что вы получите из этой статьи
- Пошаговые примеры кода для нескольких типов прыжков и связанных механик.
- Практические советы по балансу и отладке.
- Контрольные списки для разработчика, дизайнера и тестировщика.
- Мини-методологию и набор тестов приёмки.
Быстрый старт и установка
Убедитесь, что у вас установлен pip, затем установите Arcade:
pip install arcadeПримеры ниже используют простую физику: вертикальная скорость (player_dy), горизонтальная скорость (player_dx), постоянное ускорение вниз (GRAVITY) и простую коллизию по высоте платформы.
Создание простой игры
Первый пример показывает базовую сцену: игрок падает под действием гравитации и останавливается на статической платформе.
Создайте файл simple-game.py и вставьте код:
import arcade
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
PLAYER_RADIUS = 20
PLATFORM_WIDTH = 200
PLATFORM_HEIGHT = 20
GRAVITY = 0.5
class GameWindow(arcade.Window):
def __init__(self):
super().__init__(SCREEN_WIDTH, SCREEN_HEIGHT, "Jumping Mechanics")
self.player_x = SCREEN_WIDTH // 2
self.player_y = SCREEN_HEIGHT // 2
self.player_dx = 0
self.player_dy = 0
self.platform_x = SCREEN_WIDTH // 2
self.platform_y = SCREEN_HEIGHT // 4
def on_draw(self):
arcade.start_render()
arcade.draw_circle_filled(self.player_x, self.player_y, PLAYER_RADIUS, arcade.color.BLUE)
arcade.draw_rectangle_filled(self.platform_x, self.platform_y, PLATFORM_WIDTH, PLATFORM_HEIGHT, arcade.color.GREEN)
def on_update(self, delta_time):
# Применяем гравитацию и обновляем позицию
self.player_dy -= GRAVITY
self.player_y += self.player_dy
# Простая проверка коллизии по вертикали: если ниже поверхности платформы — ставим на неё
ground_y = self.platform_y + PLATFORM_HEIGHT / 2 + PLAYER_RADIUS
if self.player_y < ground_y:
self.player_y = ground_y
self.player_dy = 0
if __name__ == "__main__":
window = GameWindow()
arcade.run()При запуске персонаж упадёт на платформу и остановится на её вершине.
Добавление простого прыжка
Добавим обработку нажатия клавиши вверх, чтобы персонаж мог прыгать только находясь на земле.
Файл jump.py (модифицированный класс):
import arcade
# Используем те же константы, что и в простом примере
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
PLAYER_RADIUS = 20
PLATFORM_WIDTH = 200
PLATFORM_HEIGHT = 20
GRAVITY = 0.5
JUMP_VELOCITY = 10
class GameWindow(arcade.Window):
def __init__(self):
super().__init__(SCREEN_WIDTH, SCREEN_HEIGHT, "Jumping Mechanics")
self.player_x = SCREEN_WIDTH // 2
self.player_y = SCREEN_HEIGHT // 2
self.player_dx = 0
self.player_dy = 0
self.platform_x = SCREEN_WIDTH // 2
self.platform_y = SCREEN_HEIGHT // 4
def on_draw(self):
arcade.start_render()
arcade.draw_circle_filled(self.player_x, self.player_y, PLAYER_RADIUS, arcade.color.BLUE)
arcade.draw_rectangle_filled(self.platform_x, self.platform_y, PLATFORM_WIDTH, PLATFORM_HEIGHT, arcade.color.GREEN)
def on_key_press(self, key, modifiers):
# Проверяем, на земле ли игрок
ground_y = self.platform_y + PLATFORM_HEIGHT / 2 + PLAYER_RADIUS
if key == arcade.key.UP and abs(self.player_y - ground_y) < 1e-6:
self.player_dy = JUMP_VELOCITY
def on_update(self, delta_time):
self.player_dy -= GRAVITY
self.player_y += self.player_dy
ground_y = self.platform_y + PLATFORM_HEIGHT / 2 + PLAYER_RADIUS
if self.player_y < ground_y:
self.player_y = ground_y
self.player_dy = 0
if __name__ == "__main__":
window = GameWindow()
arcade.run()Заметьте: мы сравниваем y с ground_y с допуском, чтобы избежать проблем с плавающей точкой.
Добавление двойного прыжка
Для двойного прыжка добавим счётчик прыжков. Первый прыжок выполняется с земли, второй — в воздухе.
Файл double-jump.py:
import arcade
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
PLAYER_RADIUS = 20
PLATFORM_WIDTH = 200
PLATFORM_HEIGHT = 20
GRAVITY = 0.5
JUMP_VELOCITY = 10
MAX_JUMPS = 2
class GameWindow(arcade.Window):
def __init__(self):
super().__init__(SCREEN_WIDTH, SCREEN_HEIGHT, "Jumping Mechanics")
self.player_x = SCREEN_WIDTH // 2
self.player_y = SCREEN_HEIGHT // 2
self.player_dx = 0
self.player_dy = 0
self.platform_x = SCREEN_WIDTH // 2
self.platform_y = SCREEN_HEIGHT // 4
self.jump_count = 0
def on_draw(self):
arcade.start_render()
arcade.draw_circle_filled(self.player_x, self.player_y, PLAYER_RADIUS, arcade.color.BLUE)
arcade.draw_rectangle_filled(self.platform_x, self.platform_y, PLATFORM_WIDTH, PLATFORM_HEIGHT, arcade.color.GREEN)
def on_key_press(self, key, modifiers):
ground_y = self.platform_y + PLATFORM_HEIGHT / 2 + PLAYER_RADIUS
on_ground = abs(self.player_y - ground_y) < 1e-6
if key == arcade.key.UP and self.jump_count < MAX_JUMPS:
self.player_dy = JUMP_VELOCITY
self.jump_count += 1
if on_ground:
self.jump_count = 0
def on_update(self, delta_time):
self.player_dy -= GRAVITY
self.player_y += self.player_dy
ground_y = self.platform_y + PLATFORM_HEIGHT / 2 + PLAYER_RADIUS
if self.player_y < ground_y:
self.player_y = ground_y
self.player_dy = 0
self.jump_count = 0
if __name__ == "__main__":
window = GameWindow()
arcade.run()Таким образом первая и вторая активации клавиши UP выполняют прыжки, а счётчик сбрасывается при касании земли.
Переменная высота прыжка
Чтобы игрок мог контролировать высоту прыжка, увеличивайте силу прыжка, пока удерживается кнопка, и выпускайте — применяйте накопленный импульс.
Файл variable-jump.py:
import arcade
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
PLAYER_RADIUS = 20
PLATFORM_WIDTH = 200
PLATFORM_HEIGHT = 20
GRAVITY = 0.5
JUMP_POWER_INCREMENT = 0.8
MAX_JUMP_POWER = 16
MIN_JUMP_POWER = 6
class GameWindow(arcade.Window):
def __init__(self):
super().__init__(SCREEN_WIDTH, SCREEN_HEIGHT, "Jumping Mechanics")
self.player_x = SCREEN_WIDTH // 2
self.player_y = SCREEN_HEIGHT // 2
self.player_dx = 0
self.player_dy = 0
self.platform_x = SCREEN_WIDTH // 2
self.platform_y = SCREEN_HEIGHT // 4
self.jump_power = 0
self.jump_pressed = False
def on_draw(self):
arcade.start_render()
arcade.draw_circle_filled(self.player_x, self.player_y, PLAYER_RADIUS, arcade.color.BLUE)
arcade.draw_rectangle_filled(self.platform_x, self.platform_y, PLATFORM_WIDTH, PLATFORM_HEIGHT, arcade.color.GREEN)
def on_key_press(self, key, modifiers):
ground_y = self.platform_y + PLATFORM_HEIGHT / 2 + PLAYER_RADIUS
if key == arcade.key.UP and abs(self.player_y - ground_y) < 1e-6:
self.jump_pressed = True
self.jump_power = MIN_JUMP_POWER
def on_key_release(self, key, modifiers):
if key == arcade.key.UP and self.jump_pressed:
# Применяем накопленную силу прыжка
self.player_dy = min(self.jump_power, MAX_JUMP_POWER)
self.jump_pressed = False
self.jump_power = 0
def on_update(self, delta_time):
# Наращиваем силу прыжка, пока удерживают кнопку
if self.jump_pressed:
self.jump_power += JUMP_POWER_INCREMENT
if self.jump_power > MAX_JUMP_POWER:
self.jump_power = MAX_JUMP_POWER
self.player_dy -= GRAVITY
self.player_y += self.player_dy
ground_y = self.platform_y + PLATFORM_HEIGHT / 2 + PLAYER_RADIUS
if self.player_y < ground_y:
self.player_y = ground_y
self.player_dy = 0
if __name__ == "__main__":
window = GameWindow()
arcade.run()Этот подход даёт игроку тонкий контроль: короткое нажатие — низкий прыжок, удержание — высокий.
Воздушный рывок (air dash)
Air dash даёт дополнительные опции маневрирования в воздухе. Ниже — простая версия, где рывок сбрасывает горизонтальную скорость и даёт краткий импульс.
Файл air-dash.py:
import arcade
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
PLAYER_RADIUS = 20
PLATFORM_WIDTH = 200
PLATFORM_HEIGHT = 20
GRAVITY = 0.5
JUMP_VELOCITY = 10
AIR_DASH_DISTANCE = 200
MAX_AIR_DASHES = 1
class GameWindow(arcade.Window):
def __init__(self):
super().__init__(SCREEN_WIDTH, SCREEN_HEIGHT, "Jumping Mechanics")
self.player_x = SCREEN_WIDTH // 2
self.player_y = SCREEN_HEIGHT // 2
self.player_dx = 0
self.player_dy = 0
self.platform_x = SCREEN_WIDTH // 2
self.platform_y = SCREEN_HEIGHT // 4
self.on_ground = False
self.air_dashes = 0
def on_draw(self):
arcade.start_render()
arcade.draw_circle_filled(self.player_x, self.player_y, PLAYER_RADIUS, arcade.color.BLUE)
arcade.draw_rectangle_filled(self.platform_x, self.platform_y, PLATFORM_WIDTH, PLATFORM_HEIGHT, arcade.color.GREEN)
def on_key_press(self, key, modifiers):
ground_y = self.platform_y + PLATFORM_HEIGHT / 2 + PLAYER_RADIUS
on_ground = abs(self.player_y - ground_y) < 1e-6
if key == arcade.key.UP and on_ground:
self.player_dy = JUMP_VELOCITY
elif key == arcade.key.SPACE and self.air_dashes < MAX_AIR_DASHES:
# Простой рывок вправо; можно расширить для направления
self.player_dx = AIR_DASH_DISTANCE
self.air_dashes += 1
def on_update(self, delta_time):
# Горизонтальная декомпозиция скорости (фрикция)
if self.player_dx > 0:
self.player_dx -= 20 * delta_time
if self.player_dx < 0:
self.player_dx = 0
self.player_dy -= GRAVITY
self.player_y += self.player_dy
self.player_x += self.player_dx * delta_time
# Границы экрана
if self.player_x < PLAYER_RADIUS:
self.player_x = PLAYER_RADIUS
self.player_dx = 0
elif self.player_x > SCREEN_WIDTH - PLAYER_RADIUS:
self.player_x = SCREEN_WIDTH - PLAYER_RADIUS
self.player_dx = 0
ground_y = self.platform_y + PLATFORM_HEIGHT / 2 + PLAYER_RADIUS
if self.player_y < ground_y:
self.player_y = ground_y
self.player_dy = 0
self.on_ground = True
self.air_dashes = 0
else:
self.on_ground = False
if __name__ == "__main__":
window = GameWindow()
arcade.run()При выполнении рывка персонаж быстро смещается по горизонтали; после касания земли счётчик рывков сбрасывается.
Лучшие практики по реализации прыжков
Баланс высоты и длительности
Экспериментируйте с JUMP_VELOCITY и GRAVITY. Ментальная модель: высота прыжка растёт с квадратом начальной скорости при фиксированной гравитации. Если прыжок кажется “высоким, но медленным” — увеличьте скорость и увеличьте гравитацию.
Отзывчивость и обратная связь
Добавляйте визуальные (анимация, частицы) и звуковые эффекты при старте прыжка, фазе полёта и приземлении. Это делает прыжки ощущаемыми.
Надёжная коллизия
Проверяйте коллизии аккуратно: используйте небольшой допуск при сравнении координат, учитывайте скорость при попадании в платформу (например, если скорость очень высокая, можно выполнять коррекцию позиции и предотвращать проход через платформу).
Разделение логики
Разделяйте физику (обновление скоростей/позиции) и ввод. Это упрощает тестирование и расширение механики.
Когда механика может не подойти (контрпримеры)
- Проект с реалистичной физикой: простая вертикальная модель и фиксированный GRAVITY могут выглядеть нереалистично.
- Сложные коллайдеры и наклонные поверхности потребуют физического движка или более сложных расчётов.
- Сетевые игры: предсказание и компенсация лага потребуют дополнительной логики синхронизации.
Альтернативные подходы
- Использовать Box2D или pymunk для точной физики и коллизий.
- Реализовать вспомогательный слой полу-физики: отдельный обработчик платформ и солидных тел.
- Псевдо-физика: менять анимации и ограничения скорости вместо реальной физики для большего контроля геймдизайна.
Ментальные модели и эвристики
- “Сила прыжка vs гравитация”: увеличьте гравитацию, если хотите более «острое» приземление.
- “Короткое нажатие = маленький прыжок”: накапливайте энергию прыжка при удержании.
- “Сколько действий в воздухе”: ограничивайте дополнительные прыжки/рывки счётчиками, чтобы избежать бесконечных комбинаций.
Фактбокс: ключевые параметры (пример)
- Экран: 800×600 пикселей
- Радиус игрока: 20 px
- Платформа: 200×20 px
- Гравитация: 0.5 (условные единицы в кадре)
- Обычный прыжок: 10 (начальная вертикальная скорость)
- Максимальный накопленный прыжок: 16
Роль‑ориентированные чек-листы
Для программиста:
- Разделение ввода и физики
- Надёжная проверка касания земли с допуском
- Сброс счётчиков прыжков при касании земли
- Обработка граничных условий и скоростей
Для гейм-дизайнера:
- Параметры прыжка тестированы на нескольких уровнях
- Есть визуальная и звуковая обратная связь
- Прочувствуйте темп уровней с текущими настройками
Для тестировщика:
- Тесты на стабильность при высокой скорости
- Тесты комбинаций (двойной прыжок, рывок + прыжок)
- Проверка при коллизии с краями экрана
Критерии приёмки
- Игрок не проходит сквозь платформы при нормальных скоростях.
- Прыжок выполняется только при касании земли (или в рамках правил двойного прыжка).
- Двойной прыжок работает: максимум два подъёма в воздухе до касания земли.
- Переменная высота: короткое/длинное удержание даёт заметно разную высоту.
Тест-кейсы
- Нормальный прыжок: нажать UP на земле, проверить, что y увеличивается и потом возвращается на платформу.
- Двойной прыжок: на земле нажать UP, затем снова UP в воздухе — проверить, что произошёл второй подъём.
- Переменная высота: короткое нажатие vs удержание — сравнить высоты.
- Air dash: выполнить рывок в воздухе, проверить горизонтальную дистанцию и сброс счётчика после касания земли.
- Граничные условия: прыжок у края платформы и вблизи границ экрана.
Советы по отладке и измерениям
- Выводите текущие значения player_y, player_dy, jump_count в консоль или HUD для быстрой отладки.
- Локально меняйте параметры и проходите уровни — наблюдайте, как меняется ощущение.
Совместимость и миграция
- Arcade стабильно работает на Windows, macOS и Linux.
- При переносе на движок с физикой (Box2D/pymunk) переносите лишь игровую логику, параметры силы и гравитации нужно будет откалибровать заново.
Короткое объявление для сообщества (100–200 слов)
Реализовали гибкие прыжковые механики для платформера на Python с Arcade: базовое падение и платформа, одиночный и двойной прыжок, переменная высота и воздушный рывок. В статье — готовые примеры кода, чек-листы для разработчиков и тестов, а также рекомендации по балансу и отладке. Подходит как для учебных проектов, так и для прототипирования игры.
Резюме
- Начните с простой физики: GRAVITY + player_dy.
- Добавьте понятную проверку “на земле” и счётчики для дополнительных прыжков.
- Переменная высота и air dash дают глубокий контроль над геймплеем.
- Тестируйте комбинации и давайте игроку визуальную обратную связь.
Важно: подбирайте параметры под конкретную механику вашего уровня — то, что работает в учебном примере, может требовать балансировки для финального продукта.
Похожие материалы
Как удалить аккаунт Revolut — полное руководство
3D‑текст в CorelDRAW с Extrude
Как включить авто‑субтитры в TikTok
Higan для SNES на Ubuntu — точная эмуляция
Winget: как использовать Windows Package Manager