Гид по технологиям

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

6 min read Game Dev Обновлено 26 Nov 2025
Прыжки в платформере на Python с Arcade
Прыжки в платформере на 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

Роль‑ориентированные чек-листы

Для программиста:

  • Разделение ввода и физики
  • Надёжная проверка касания земли с допуском
  • Сброс счётчиков прыжков при касании земли
  • Обработка граничных условий и скоростей

Для гейм-дизайнера:

  • Параметры прыжка тестированы на нескольких уровнях
  • Есть визуальная и звуковая обратная связь
  • Прочувствуйте темп уровней с текущими настройками

Для тестировщика:

  • Тесты на стабильность при высокой скорости
  • Тесты комбинаций (двойной прыжок, рывок + прыжок)
  • Проверка при коллизии с краями экрана

Критерии приёмки

  • Игрок не проходит сквозь платформы при нормальных скоростях.
  • Прыжок выполняется только при касании земли (или в рамках правил двойного прыжка).
  • Двойной прыжок работает: максимум два подъёма в воздухе до касания земли.
  • Переменная высота: короткое/длинное удержание даёт заметно разную высоту.

Тест-кейсы

  1. Нормальный прыжок: нажать UP на земле, проверить, что y увеличивается и потом возвращается на платформу.
  2. Двойной прыжок: на земле нажать UP, затем снова UP в воздухе — проверить, что произошёл второй подъём.
  3. Переменная высота: короткое нажатие vs удержание — сравнить высоты.
  4. Air dash: выполнить рывок в воздухе, проверить горизонтальную дистанцию и сброс счётчика после касания земли.
  5. Граничные условия: прыжок у края платформы и вблизи границ экрана.

Советы по отладке и измерениям

  • Выводите текущие значения player_y, player_dy, jump_count в консоль или HUD для быстрой отладки.
  • Локально меняйте параметры и проходите уровни — наблюдайте, как меняется ощущение.

Совместимость и миграция

  • Arcade стабильно работает на Windows, macOS и Linux.
  • При переносе на движок с физикой (Box2D/pymunk) переносите лишь игровую логику, параметры силы и гравитации нужно будет откалибровать заново.

Короткое объявление для сообщества (100–200 слов)

Реализовали гибкие прыжковые механики для платформера на Python с Arcade: базовое падение и платформа, одиночный и двойной прыжок, переменная высота и воздушный рывок. В статье — готовые примеры кода, чек-листы для разработчиков и тестов, а также рекомендации по балансу и отладке. Подходит как для учебных проектов, так и для прототипирования игры.

Резюме

  • Начните с простой физики: GRAVITY + player_dy.
  • Добавьте понятную проверку “на земле” и счётчики для дополнительных прыжков.
  • Переменная высота и air dash дают глубокий контроль над геймплеем.
  • Тестируйте комбинации и давайте игроку визуальную обратную связь.

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

Поделиться: X/Twitter Facebook LinkedIn Telegram
Автор
Редакция

Похожие материалы

Как удалить аккаунт Revolut — полное руководство
Финансы

Как удалить аккаунт Revolut — полное руководство

3D‑текст в CorelDRAW с Extrude
Графический Дизайн

3D‑текст в CorelDRAW с Extrude

Как включить авто‑субтитры в TikTok
Социальные сети

Как включить авто‑субтитры в TikTok

Higan для SNES на Ubuntu — точная эмуляция
Эмуляция

Higan для SNES на Ubuntu — точная эмуляция

Winget: как использовать Windows Package Manager
Инструменты

Winget: как использовать Windows Package Manager

Установка и настройка тем в Windows
Windows

Установка и настройка тем в Windows