---
key: lesson/game-loop
type: lesson
id: game-loop
lang: ru
title: Игровой цикл и время
summary: >-
  Отделяем скорость игры от частоты кадров и проверяем поведение при паузах и
  просадках FPS.
updatedAt: '2026-10-20'
status: active
url: 'https://gamemechanics.pro/ru/lessons/game-loop/'
jsonUrl: 'https://gamemechanics.pro/api/v1/knowledge/ru/lesson/game-loop.json'
markdownUrl: 'https://gamemechanics.pro/content/knowledge/ru/lesson/game-loop.md'
aliases: []
tags:
  - game-loop
  - time
  - simulation
sourceIds:
  - source-4794cbcf5206cc3d
  - source-61d9bfebd277d850
  - source-e55fb78e3762cd48
sources:
  - id: source-4794cbcf5206cc3d
    title: 'Robert Nystrom: Game Loop'
    url: 'https://gameprogrammingpatterns.com/game-loop.html'
    verifiedAt: null
  - id: source-61d9bfebd277d850
    title: 'MDN: requestAnimationFrame'
    url: >-
      https://developer.mozilla.org/en-US/docs/Web/API/Window/requestAnimationFrame
    verifiedAt: null
  - id: source-e55fb78e3762cd48
    title: 'Glenn Fiedler: Fix Your Timestep!'
    url: >-
      https://github.com/mas-bandwidth/gafferongames/blob/main/content/post/fix_your_timestep.md
    verifiedAt: null
relations:
  - type: requires
    direction: outgoing
    label: Перед началом
    key: lesson/scope-and-prototype
    title: Скоуп и проверяемый прототип
    url: 'https://gamemechanics.pro/ru/lessons/scope-and-prototype/'
    jsonUrl: >-
      https://gamemechanics.pro/api/v1/knowledge/ru/lesson/scope-and-prototype.json
    markdownUrl: >-
      https://gamemechanics.pro/content/knowledge/ru/lesson/scope-and-prototype.md
  - type: requires
    direction: incoming
    label: Продолжить изучение
    key: lesson/input-and-feedback
    title: Ввод и обратная связь
    url: 'https://gamemechanics.pro/ru/lessons/input-and-feedback/'
    jsonUrl: >-
      https://gamemechanics.pro/api/v1/knowledge/ru/lesson/input-and-feedback.json
    markdownUrl: >-
      https://gamemechanics.pro/content/knowledge/ru/lesson/input-and-feedback.md
  - type: requires
    direction: incoming
    label: Продолжить изучение
    key: lesson/collision-basics
    title: Основы столкновений
    url: 'https://gamemechanics.pro/ru/lessons/collision-basics/'
    jsonUrl: 'https://gamemechanics.pro/api/v1/knowledge/ru/lesson/collision-basics.json'
    markdownUrl: 'https://gamemechanics.pro/content/knowledge/ru/lesson/collision-basics.md'
  - type: requires
    direction: incoming
    label: Продолжить изучение
    key: lesson/performance-budget
    title: Бюджет производительности
    url: 'https://gamemechanics.pro/ru/lessons/performance-budget/'
    jsonUrl: >-
      https://gamemechanics.pro/api/v1/knowledge/ru/lesson/performance-budget.json
    markdownUrl: >-
      https://gamemechanics.pro/content/knowledge/ru/lesson/performance-budget.md
  - type: contains
    direction: incoming
    label: Учебные маршруты
    key: path/first-prototype
    title: Первый проверяемый прототип
    url: 'https://gamemechanics.pro/ru/learn/first-prototype/'
    jsonUrl: 'https://gamemechanics.pro/api/v1/knowledge/ru/path/first-prototype.json'
    markdownUrl: 'https://gamemechanics.pro/content/knowledge/ru/path/first-prototype.md'
  - type: requires
    direction: incoming
    label: Продолжить изучение
    key: path/npc-behavior
    title: Поведение NPC
    url: 'https://gamemechanics.pro/ru/learn/npc-behavior/'
    jsonUrl: 'https://gamemechanics.pro/api/v1/knowledge/ru/path/npc-behavior.json'
    markdownUrl: 'https://gamemechanics.pro/content/knowledge/ru/path/npc-behavior.md'
  - type: uses
    direction: outgoing
    label: Источники в подборке
    key: resource/game-loop-pattern
    title: 'Игровой цикл: Game Programming Patterns'
    url: 'https://gamemechanics.pro/ru/resources/#resource-game-loop-pattern'
    jsonUrl: >-
      https://gamemechanics.pro/api/v1/knowledge/ru/resource/game-loop-pattern.json
    markdownUrl: >-
      https://gamemechanics.pro/content/knowledge/ru/resource/game-loop-pattern.md
  - type: uses
    direction: outgoing
    label: Источники в подборке
    key: resource/animation-frame
    title: requestAnimationFrame на MDN
    url: 'https://gamemechanics.pro/ru/resources/#resource-animation-frame'
    jsonUrl: >-
      https://gamemechanics.pro/api/v1/knowledge/ru/resource/animation-frame.json
    markdownUrl: 'https://gamemechanics.pro/content/knowledge/ru/resource/animation-frame.md'
  - type: uses
    direction: outgoing
    label: Источники в подборке
    key: resource/fixed-timestep
    title: Fix Your Timestep!
    url: 'https://gamemechanics.pro/ru/resources/#resource-fixed-timestep'
    jsonUrl: 'https://gamemechanics.pro/api/v1/knowledge/ru/resource/fixed-timestep.json'
    markdownUrl: 'https://gamemechanics.pro/content/knowledge/ru/resource/fixed-timestep.md'
placements: []
supersededBy: []
attributes:
  category: foundations
  level: beginner
  minutes: 6
endsAt: null
provenance: >-
  Авторский материал gamemechanics.pro. Учебные примеры требуют проверки в своём
  проекте.
license: CC-BY-4.0
codeLicense: MIT
attribution: gamemechanics.pro contributors
---
# Игровой цикл и время

id: game-loop
type: lesson
key: lesson/game-loop
lang: ru
status: active
url: https://gamemechanics.pro/ru/lessons/game-loop/

Отделяем скорость игры от частоты кадров и проверяем поведение при паузах и просадках FPS.

## Что нужно знать

Достаточно понимать переменные, функции и координаты. После урока вы сможете объяснить, кто обновляет мир, в каких единицах задана скорость и почему один нарисованный кадр не всегда равен одному шагу симуляции.

## Принцип

Игровой цикл связывает ввод, изменение состояния и отображение результата. Даже если персонаж стоит, мир может продолжать жить. В готовом движке этот цикл уже существует: ваша задача подключить логику к подходящим точкам обновления. Общая модель разобрана в [главе Game Loop](https://gameprogrammingpatterns.com/game-loop.html).

Запись `x += 3` означает три единицы за вызов. При разной частоте вызовов персонаж проходит разное расстояние. Запись `x += speed * dt` задаёт движение через прошедшее время, где `speed` измеряется в единицах в секунду, а `dt` в секундах. Но это само по себе не делает любую физическую модель устойчивой.

Для чувствительной к шагу симуляции используют фиксированный интервал обновления. Накопленное реальное время расходуется на несколько одинаковых шагов; отрисовка может происходить реже или чаще. Ограничение числа догоняющих шагов требует явного решения: замедлять игровой мир или иначе обрабатывать перегрузку. Подробности есть в [Fix Your Timestep!](https://github.com/mas-bandwidth/gafferongames/blob/main/content/post/fix_your_timestep.md).

## Практический пример

Начните с одного квадрата без столкновений. Пусть он движется со скоростью 120 единиц в секунду. За две секунды непрерывного движения ожидается 240 единиц независимо от количества показанных кадров.

```text
update(dtSeconds, input):
    if input.moveRight:
        player.x += 120 * dtSeconds

render():
    drawSquare(player.x, player.y)
```

Это учебный псевдокод, а не готовый цикл движка. Сначала вызовите `update` 120 раз с шагом `1/60`, затем 60 раз с шагом `1/30`. Сравните координаты с небольшой допустимой погрешностью. Отдельно попробуйте меняющиеся интервалы с той же суммой времени.

В браузере `requestAnimationFrame` вызывает функцию перед перерисовкой и обычно приостанавливается в фоновых вкладках. Его временная метка задана в миллисекундах. Эти условия документирует [MDN](https://developer.mozilla.org/en-US/docs/Web/API/Window/requestAnimationFrame). При возвращении из фона задайте политику возобновления: например, сбросить предыдущую метку времени и продолжить с паузы.

## Частые ошибки

Не обновляйте координаты одновременно в физическом и визуальном callback (обработчике, который вызывает движок). Не применяйте `dt` дважды, если метод движка уже ожидает скорость. Не запускайте второй цикл при каждом рестарте сцены. Не используйте скрытие вкладки как неявную паузу: звук, сетевые события и таймеры могут иметь другой жизненный цикл.

Сначала проверяйте движение без интерполяции. Когда логика верна, визуальное сглаживание можно добавить отдельно. Иначе плавная картинка способна скрыть ошибку в скорости или порядке обновления.

## Проверка результата

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

## Задание для ИИ-агента

> Найди владельца игрового цикла и все места изменения координат игрока. Опиши единицы скорости и времени. Предложи минимальное исправление зависимости движения от FPS и проверь путь за две секунды при нескольких последовательностях dt. Отдельно укажи поведение паузы и восстановления фокуса. Не меняй физический backend без доказанной необходимости.

## Связанные материалы

- Перед началом: [Скоуп и проверяемый прототип](https://gamemechanics.pro/ru/lessons/scope-and-prototype/) (key: lesson/scope-and-prototype)
- Продолжить изучение: [Ввод и обратная связь](https://gamemechanics.pro/ru/lessons/input-and-feedback/) (key: lesson/input-and-feedback)
- Продолжить изучение: [Основы столкновений](https://gamemechanics.pro/ru/lessons/collision-basics/) (key: lesson/collision-basics)
- Продолжить изучение: [Бюджет производительности](https://gamemechanics.pro/ru/lessons/performance-budget/) (key: lesson/performance-budget)
- Учебные маршруты: [Первый проверяемый прототип](https://gamemechanics.pro/ru/learn/first-prototype/) (key: path/first-prototype)
- Продолжить изучение: [Поведение NPC](https://gamemechanics.pro/ru/learn/npc-behavior/) (key: path/npc-behavior)
- Источники в подборке: [Игровой цикл: Game Programming Patterns](https://gamemechanics.pro/ru/resources/#resource-game-loop-pattern) (key: resource/game-loop-pattern)
- Источники в подборке: [requestAnimationFrame на MDN](https://gamemechanics.pro/ru/resources/#resource-animation-frame) (key: resource/animation-frame)
- Источники в подборке: [Fix Your Timestep!](https://gamemechanics.pro/ru/resources/#resource-fixed-timestep) (key: resource/fixed-timestep)

## Источники и происхождение

Авторский материал gamemechanics.pro. Учебные примеры требуют проверки в своём проекте.

- [Robert Nystrom: Game Loop](https://gameprogrammingpatterns.com/game-loop.html) (id: source-4794cbcf5206cc3d)
- [MDN: requestAnimationFrame](https://developer.mozilla.org/en-US/docs/Web/API/Window/requestAnimationFrame) (id: source-61d9bfebd277d850)
- [Glenn Fiedler: Fix Your Timestep!](https://github.com/mas-bandwidth/gafferongames/blob/main/content/post/fix_your_timestep.md) (id: source-e55fb78e3762cd48)

CC-BY-4.0 · gamemechanics.pro contributors
