Паттерны — игровой цикл и конечные автоматы
Игровой цикл (game loop) — повторяющаяся последовательность шагов, из которой складывается интерактивная графика. Каждый проход цикла — один кадр (frame).
Схема цикла
while (running):
dt = measure_delta_time()
process_input()
update(dt)
render()
sync_to_display()
Иллюзия движения — из серии статичных картинок, как в мультфильме.
Порядок шагов
- Input — прочитать клавиши и мышь в начале кадра
- Update — изменить модель с учётом
dt - Render — нарисовать актуальное состояние (часто после очистки холста)
Если вызвать render до update, на экране окажется кадр на один шаг старее логики.
Delta time (dt)
Delta time — время в секундах с прошлого кадра.
Формула x += vx * dt делает скорость независимой от FPS (частоты кадров). Без dt игра на 144 Гц движется быстрее, чем на 60 Гц.
Типичные ловушки:
- слишком большой
dtпри лаге — объект "проскакивает" сквозь стену; ограничениеdt = Math.min(dt, 0.05) - забытый
dtна одной из осей
Синхронизация по платформам
| Платформа | Механизм | Примечание |
|---|---|---|
| Браузер | requestAnimationFrame | ~60 Гц, пауза во вкладке |
| Pygame | clock.tick(60) | блокирует до следующего слота |
| OpenGL | glfwSwapBuffers, SDL_GL_SwapWindow | опционально V-Sync |
| Unity | Update() | физика в FixedUpdate |
Пример цикла — code-418-1-001, демо слоёв.
Fixed timestep
Физика иногда обновляется фиксированным шагом (1/60 с), рендер — с интерполяцией между двумя состояниями. Симуляция стабильнее при скачках FPS.
Порядок отрисовки кадра
clear entire framebuffer
draw background
draw world entities (sorted by z / layer)
draw particles
draw UI overlay
present / swap
Painter's algorithm — в 2D дальние объекты рисуют раньше ближних. В 3D перекрытие решает Z-buffer (буфер глубины).
Конечный автомат (FSM)
FSM (finite state machine) — явный список режимов игры и правил перехода между ними.
| Состояние | Update | Render |
|---|---|---|
MENU | навигация по пунктам | фон и кнопки |
PLAYING | физика, враги | мир и HUD |
PAUSED | только ввод "продолжить" | замороженный мир и оверлей |
GAME_OVER | таймер рестарта | итоговый экран |
switch (gameState) {
case 'MENU': updateMenu(); renderMenu(); break;
case 'PLAYING': updateWorld(); renderWorld(); break;
}
Плюсы FSM:
- физика не запускается в меню
- разные обработчики ввода на режим
- проще тестировать
Иерархические FSM: внутри PLAYING — подсостояния CUTSCENE, DIALOG.
FSM и набор флагов
Вариант с if (paused) return в каждой функции быстро превращается в запутанный код. FSM задаёт карту режимов в одном месте.
Соседние паттерны
| Паттерн | Роль |
|---|---|
| Entity-Component | данные сущности разбиты на компоненты |
| Object Pool | переиспользование пуль без сборщика мусора |
| State | объект с enter, update, exit на состояние |
| Command | очередь действий ввода |
Unity: MonoBehaviour.Update(), LateUpdate(). Godot: _process(delta).