---
title: "Идеальный прыжок и секрет Coyote Time: почему одни платформеры ощущаются отзывчивыми, а другие нет"
description: "Разбор физики и таймингов прыжка в 2D-платформере: формулы скорости и гравитации по высоте и времени, окна Coyote Time (80–120 мс) и Jump Buffering и проверенный код прыжка на JavaScript."
slug: idealnyj-pryzhok-i-sekret-coyote-time
date: 2026-10-29
updated: 2026-11-02
scheduled_at: "2026-10-29T14:00:00+03:00"
rubric: gejmdizajn-i-mehaniki
tags: ["platformer", "gejmdizajn", "fizika", "novichkam", "profi"]
reading_time: 10
draft: false
summary: "Отзывчивый прыжок в 2D-платформере строится не на симметричной школьной параболе, а на пяти управляемых допусках: окне прощения после схода с уступа (Coyote Time, 80–120 мс), буферизации раннего нажатия до приземления (Jump Buffering, 100–150 мс), ускоренном падении вниз (множитель гравитации 1,6–2,2x), отсечении скорости при раннем отпускании кнопки и расчёте гравитации напрямую из высоты в пикселях и времени подъёма."
---

## Коротко

Прыжок в 2D-платформере ощущается отзывчивым тогда, когда игра компенсирует человеческую задержку зрительно-моторной реакции и считает параметры физики от геометрии клеток уровня, а не от случайных констант. Пять приёмов — окно «времени койота» (Coyote Time, `80–120 мс`), буферизация нажатия перед приземлением (Jump Buffering, `100–150 мс`), асимметричная гравитация на спуске (`1,6–2,2x`), регулировка высоты удержанием кнопки и зависание в вершине прыжка — превращают «ватное» управление в точное. В статье приведены точные формулы перевода высоты в пикселях в скорость и гравитацию, таблица таймингов в миллисекундах и проверенный в Node.js код прыжка с окнами Coyote Time и буфером нажатия.

## Содержание

1. Почему честная школьная парабола ломает ощущение прыжка
2. Как вывести скорость и гравитацию из высоты в пикселях и времени подъёма
3. Секрет №1: Coyote Time («время койота») при сходе с края уступа
4. Секрет №2: Jump Buffering (буферизация нажатия до касания земли)
5. Секрет №3: Асимметричная гравитация, отсечение прыжка и зависание в вершине
6. Эталонная таблица таймингов отзывчивого 2D-прыжка
7. Практический сценарий: прыжок с Coyote Time и буфером на JavaScript
8. Когда вам это не подойдёт

## Почему честная школьная парабола ломает ощущение прыжка

Школьная формула свободного падения с постоянным ускорением `g` и строгим условием «прыгать можно только пока ноги касаются земли» создаёт в 2D-игре две проблемы: персонаж слишком медленно падает вниз и не срабатывает на краю пропасти.

Время простой зрительно-моторной реакции человека на визуальный стимул измеряется сотнями миллисекунд: медиана онлайн-теста *Human Benchmark* — `273 мс` (источник: `humanbenchmark.com/tests/reactiontime/statistics`, проверено: октябрь 2026); при частоте `60 к/с`, где один кадр длится `16,67 мс`, это около `16` кадров. Когда игрок на скорости `300 пикселей/с` бежит к обрыву и нажимает клавишу прыжка «в последний момент», его палец опускается на кнопку на `30–80 мс` позже, чем нижняя грань коллайдера персонажа покинула край платформы. Строгая физическая проверка видит, что контакта с полом уже нет, игнорирует нажатие, и герой падает в яму, а игрок считает, что «кнопка не сработала».

## Как вывести скорость и гравитацию из высоты в пикселях и времени подъёма

Профессиональные геймдизайнеры задают прыжок не подбором абстрактных сил в ньютонах, а двумя величинами, напрямую связанными с тайловой сеткой уровня: **желаемой высотой прыжка `H` (в пикселях)** и **временем достижения верхней точки `t_apex` (в секундах)**. Этот математический метод представил инженер Кайл Питтман в докладе *«Math for Game Programmers: Building a Better Jump»* на конференции GDC 2016 (источник: *GDC Vault*, 2016 год, проверено: октябрь 2026).

Из кинематических уравнений движения с постоянным ускорением на участке подъёма (`y(t) = v0 * t - 0.5 * g * t²` и `v(t_apex) = v0 - g * t_apex = 0`) однозначно выражаются гравитация подъёма `g_up` и начальная вертикальная скорость прыжка `v0`:

```text
g_up = (2 * H) / (t_apex * t_apex)
v0   = (2 * H) / t_apex
```

**Конкретный расчёт под сетку `32×32` пикселя:**
Пусть персонаж должен перепрыгивать стену высотой в 3 клетки с запасом в полклетки (`H = 3,5 × 32 = 112 пикселей`) и достигать вершины прыжка за `t_apex = 0,35 с` (`21` кадр при `60 к/с`). Подставляем значения в формулы:

```text
g_up = (2 * 112) / (0.35 * 0.35) = 224 / 0.1225 ≈ 1 828,57 пикс/с²
v0   = (2 * 112) / 0.35 = 640 пикс/с
```

При таких числах герой гарантированно поднимется ровно на `112` пикселей за `350 мс`, и левел-дизайнеру не придётся перестраивать уровни методом проб и ошибок.

## Секрет №1: Coyote Time («время койота») при сходе с края уступа

Coyote Time («время койота», названное в честь мультипликационного койота Wile E. Coyote из серии *Looney Tunes* студии Warner Bros., впервые появившегося на экране в 1949 году, который продолжает бежать по воздуху, пока не посмотрит вниз) — это таймер длительностью `80–120 мс`, разрешающий прыжок сразу после схода с платформы. В платформере *Celeste* (Maddy Makes Games, релиз 25 января 2018 года) окно Coyote Time составляет `6` кадров при `60 к/с`, то есть ровно `100 мс` (источник: константа `JumpGraceTime = 0.1f` в файле `Player.cs` открытого репозитория `github.com/NoelFB/Celeste`, опубликованного в 2020 году, проверено: октябрь 2026).

Логика реализуется одной числовой переменной `ТаймерКойота`:
1. Пока коллайдер персонажа касается земли, `ТаймерКойота` в каждом кадре приравнивается к `0.10` с (`100 мс`).
2. Когда персонаж сбегает с края платформы (но не прыгал!), `ТаймерКойота` в каждом кадре уменьшается на шаг времени `dt`.
3. Если игрок нажимает клавишу прыжка при `ТаймерКойота > 0`, прыжок срабатывает штатно, а `ТаймерКойота` немедленно обнуляется (`0`), чтобы исключить двойной прыжок в воздухе.

## Секрет №2: Jump Buffering (буферизация нажатия до касания земли)

Jump Buffering (буфер прыжка) решает зеркальную ошибку при серии прыжков по узким столбикам, когда игрок нажимает кнопку прыжка за `50–120 мс` **до того**, как ноги персонажа коснулись следующей платформы. Без буфера игра отвергает нажатие (так как в момент клика герой ещё в воздухе), и после приземления персонаж остаётся стоять на месте.

С буфером прыжка нажатие кнопки не проверяется только в один мгновенный кадр, а взводит переменную `БуферПрыжка = 0.12` с (`120 мс`, или `7` кадров при `60 к/с`):
- В каждом кадре `БуферПрыжка` убывает на `dt`;
- Как только срабатывает контакт с землёй (или активен `ТаймерКойота > 0`) **и** при этом `БуферПрыжка > 0`, персонаж мгновенно отталкивается вверх в первом же кадре приземления, а оба таймера сбрасываются в `0`.

## Секрет №3: Асимметричная гравитация, отсечение прыжка и зависание в вершине

Три дополнительных модификатора вертикальной скорости `Vy` дают игроку полный контроль над траекторией в воздухе:

1. **Ускоренное падение (Fall Multiplier):** когда персонаж летит вниз (`Vy > 0`, если ось `Y` направлена вниз), базовая гравитация умножается на коэффициент `1.8` (`g_down = 1,8 × g_up`). Подъём на `112` пикселей занимает `350 мс`, а спуск с той же высоты — около `260 мс`.
2. **Раннее отсечение прыжка (Variable Jump Cutoff):** если игрок слегка коснулся кнопки и отпустил её до достижения верхней точки (пока персонаж ещё движется вверх), вертикальная скорость умножается на `0.5` (или гравитация утраивается до конца подъёма). Это позволяет из одного базового прыжка получить и короткий подскок на 1 клетку (`32` пикселя), и полный прыжок на 3,5 клетки (`112` пикселей).
3. **Зависание в вершине (Apex Hang Time):** когда модуль вертикальной скорости вблизи пика траектории мал (`|Vy| < 60 пикс/с`), гравитация временно снижается до `0.5x`, а горизонтальная манёвренность увеличивается на `15–20%`, давая игроку долю секунды на точное прицеливание при посадке на узкий уступ.

## Эталонная таблица таймингов отзывчивого 2D-прыжка

В таблице сведены рабочие диапазоны параметров, которые можно сразу перенести в константы кода игры.

Таблица: Рекомендуемые численные параметры прыжка для 2D-платформера (сетка 32×32 пикселя)

| Параметр механики | Значение в единицах времени / физики | Эквивалент в кадрах при 60 к/с (`16,67 мс`) | Эквивалент в кадрах при 30 к/с (`33,33 мс`) | За что отвечает в ощущениях игрока |
|---|---|---|---|---|
| Высота полного прыжка (`H`) | `112 пикселей` (3,5 клетки) | — | — | Преодоление препятствий в 3 клетки высотой с запасом `16` пикселей |
| Время до вершины (`t_apex`) | `350 мс` (`0,35 с`) | `21 кадр` | `10,5 кадра` | Темп взлёта: без ощущения тяжести и без «плавания» |
| Начальная скорость (`v0`) | `640 пикс/с` | `10,67 пикс/кадр` | `21,33 пикс/кадр` | Мгновенный отрыв от поверхности |
| Гравитация подъёма (`g_up`) | `1 829 пикс/с²` | — | — | Равномерное замедление до вершины траектории |
| Множитель гравитации падения | `1,8x` (`3 292 пикс/с²`) | `~15,6 кадра` на спуск | `~7,8 кадра` на спуск | Быстрое и плотное приземление |
| Окно Coyote Time | `100 мс` (`0,10 с`) | `6 кадров` | `3 кадра` | Прощение позднего нажатия на краю пропасти |
| Окно Jump Buffering | `120 мс` (`0,12 с`) | `7 кадров` | `3,6 кадра` | Срабатывание прыжка, нажатого чуть раньше касания пола |
| Предельная скорость падения | `720 пикс/с` | `12 пикс/кадр` | `24 пикс/кадр` | Защита от пролёта сквозь тонкие платформы в глубоких шахтах |

## Практический сценарий: прыжок с Coyote Time и буфером на JavaScript

Прыжок с окнами Coyote Time (`100 мс`) и Jump Buffering (`120 мс`) укладывается в одну функцию шага физики с двумя таймерами, а проверить окна можно без графики — прогоном шагов по `1/60 с`. Код ниже проверен в Node.js 24; комментарии показывают его фактический вывод.

```js
// Параметры из таблицы: высота 112 пикс, подъём 0,35 с, ось Y направлена вниз
const H = 112, T_APEX = 0.35;
const G_UP = (2 * H) / (T_APEX * T_APEX);   // ≈ 1828,57 пикс/с²
const V0 = (2 * H) / T_APEX;                // 640 пикс/с
const FALL_MULT = 1.8, MAX_FALL = 720;
const COYOTE = 0.10, BUFFER = 0.12;

function createJumper() {
  return { vy: 0, grounded: true, coyote: COYOTE, buffer: 0, jumped: false };
}

// Один шаг физики длиной dt; pressed — нажатие в этом шаге, released — отпускание
function stepJump(p, dt, pressed, released) {
  if (pressed) p.buffer = BUFFER;
  p.coyote = p.grounded ? COYOTE : Math.max(0, p.coyote - dt);
  p.buffer = Math.max(0, p.buffer - (pressed ? 0 : dt));
  if (p.buffer > 0 && p.coyote > 0) {
    p.vy = -V0; p.grounded = false; p.coyote = 0; p.buffer = 0; p.jumped = true;
  }
  if (released && p.vy < 0) p.vy *= 0.5;           // короткий прыжок
  if (!p.grounded) {
    const g = p.vy > 0 ? G_UP * FALL_MULT : G_UP;  // ускоренное падение
    p.vy = Math.min(MAX_FALL, p.vy + g * dt);
  }
}

// Проверка 1: игрок сошёл с края и нажал прыжок через N мс
function lateJump(ms) {
  const p = createJumper(), dt = 1 / 60;
  p.grounded = false;                              // шагнул в пропасть
  const frames = Math.round(ms / (1000 * dt));
  for (let i = 0; i < frames; i++) stepJump(p, dt, false, false);
  stepJump(p, dt, true, false);
  return p.jumped;
}
console.log("нажал через 83 мс:", lateJump(83));    // true — сработало окно койота
console.log("нажал через 150 мс:", lateJump(150));  // false — окно закрылось

// Проверка 2: игрок нажал прыжок за 100 мс до касания земли
const q = createJumper(), dt = 1 / 60;
q.grounded = false; q.vy = 300;
stepJump(q, dt, true, false);                       // раннее нажатие в воздухе
for (let i = 0; i < 5; i++) stepJump(q, dt, false, false); // ещё ~83 мс полёта
q.grounded = true; q.vy = 0;                        // приземление
stepJump(q, dt, false, false);
console.log("буфер сработал при приземлении:", q.jumped); // true
```

Оба таймера уменьшаются на шаг времени `dt`, а не на `1` за кадр, поэтому при `30 к/с` окно Coyote Time остаётся `100 мс`, хотя занимает уже `3` кадра. Чтобы проверить свой прыжок, меняйте в `lateJump` задержку с шагом `16` мс и найдите последнюю, при которой прыжок ещё срабатывает.

## Когда вам это не подойдёт

Упреждающие буферы и асимметричная гравитация подходят для аркадных и скоростных платформеров, но вредят в следующих жанрах и задачах:

- **Кинематографические платформеры с инерционной анимацией шага:** в играх вроде оригинального *Prince of Persia* (Джордан Мехнер, Brøderbund, 1989 год, проверено: октябрь 2026) или *Another World* (Эрик Шайи, Delphine Software, 1991 год) задержка перед толчком намеренно привязана к фазе разбега и сгибания коленей персонажа. Добавление Coyote Time разрушит там чувство веса и риска.
- **Физические головоломки с честным законом сохранения энергии:** если механика игры требует, чтобы тело после падения с высоты `H` подскакивало на батуте строго на ту же высоту `H`, разная гравитация на подъёме (`g_up`) и спуске (`1,8 × g_up`) нарушит симметрию скорости и сломает физическую загадку.
- **Пошаговые и клеточные игры:** если персонаж прыгает ровно на одну клетку за ход, как в пошаговых головоломках, окна в миллисекундах не нужны — ввод обрабатывается по ходам, а не по кадрам.

---

Мы разрабатываем **J2DRU** — браузерный 2D игровой движок; он в разработке и публично пока не открыт, заявку можно оставить на [странице раннего доступа](/early-access?utm_source=blog&utm_medium=article&utm_campaign=idealnyj-pryzhok-i-sekret-coyote-time) (подача заявки не гарантирует приглашение).

**Читайте также:**
- [Тайловые сетки и устройство 2D-миров: от классики до современных редакторов уровней](/blog/tajlovye-setki-i-ustrojstvo-2d-mirov)
- [Игровой цикл (Game Loop) и физика столкновений (AABB, хитбоксы и триггеры) простыми словами и на уровне профи](/blog/igrovoj-cikl-i-fizika-stolknovenij-aabb)
- [Камера, параллакс и «джус» (Game Feel): как оживить плоскую сцену в 2D-игре](/blog/kamera-parallaks-i-game-feel-v-2d-igre)
