Перейти к основному содержимому

Архитектура — модель, update, render

Разработчику

Графическое приложение удобно мыслить тремя зонами — это близко к паттерну MVC (Model–View–Controller) из архитектуры приложений.


Три зоны ответственности

КомпонентЗнаетНе знает
Modelкоординаты, HP, инвентарь, таймерыразрешение экрана, цвет пикселя
Updateправила игры, физика, вводкак нарисован спрайт
Renderкак нарисовать по даннымпричину удаления объекта

Типичные ошибки при смешении слоёв:

  • вызов ctx.fillRect внутри расчёта коллизий
  • score++ внутри функции draw()

Разметка типичного файла

// 1. Константы и палитры
const COLORS = { ... };
const WIDTH = 900, HEIGHT = 700;

// 2. Модель — массивы сущностей
let balls = [ { x, y, vx, vy, color, removing }, ... ];
let player = { x, y, lives };

// 3. Ввод
const keys = {};

// 4. update(dt) — только числа
function update(dt) { ... }

// 5. render(ctx) — только отрисовка
function drawBall(b) { ... }
function render(ctx) { ... }

// 6. Цикл
function loop(t) { update(dt); render(ctx); requestAnimationFrame(loop); }

При открытии репозитория ищите функции update, render, draw — остальное приложится.

Эталон — глава 1 и каталог кода:

Код ITЗагрузка примера кода…

Код ITЗагрузка примера кода…


Модель как таблица в памяти

Записи похожи на строки таблицы — фиксируют факт, без отрисовки:

{ color: 2, dist: 850, removing: false, removeTimer: 0, scale: 1 }
{ x: 0, y: 0 }
{ main: '#ef4444', light: '#fca5a5', dark: '#b91c1c' }

Строка ball.removing = true помечает шар на удаление. Экран изменится только после render(), когда отрисовка прочитает флаг.

СлойЗадачаПример
Модельхранит состояние{ x, y, radius, color, alive }
Updateменяет состояниеball.x += ball.vx
Renderрисует по состояниюctx.arc(x, y, r, 0, Math.PI*2); ctx.fill()

Скаляры — одно значение на игру:

  • score, level, gameOver

Объекты — один персонаж или камера:

  • player, camera

Коллекции — много однотипных сущностей:

  • enemies[], particles[], bullets[]

Ресурсы — ссылки на загруженные файлы, сами пиксели в модели не хранят:

  • sprites.ball, sounds.hit

Флаги жизненного цикла — логика помечает, render реагирует:

  • alive, removing, spawnTimer

В модели обычно нет объектов отрисовки (CanvasRenderingContext2D, DOM-узлы). Исключение — UI-фреймворки, где виджет одновременно данные и картинка.


Координаты и производные поля

В Canvas и большинстве 2D API начало координат — левый верхний угол, ось Y направлена вниз:

(0,0) ──────────────► X



Y

В математических графиках и некоторых движках (например, с центром экрана) Y часто направлен вверх. При переносе кода между библиотеками проверяйте оси первым делом.

СвойствоНазначение
x, yпозиция (центр или верхний левый угол — зафиксируйте в команде)
vx, vyскорость по осям
width, heightпрямоугольник для коллизий (AABB)
radiusкруг
angleповорот в радианах или градусах
scaleмасштаб спрайта

Кэш для скорости: left, right, dist, ячейка quadtree.

Преобразования и тригонометрия — глава 5, работа с геометрией.


Retained mode и Immediate mode

РежимКто хранит сценуПримеры
RetainedплатформаDOM, WPF, Unity Hierarchy
Immediateпрограммист каждый кадрCanvas 2D, классический OpenGL

В Canvas 2D платформа буферизует команды, но состояние сцены вы восстанавливаете сами: clearRect и отрисовка всех объектов заново.


DOM, Canvas и SVG в вебе

DOM — дерево элементов. Браузер перерисовывает только изменённые области. Подходит для:

  • текст и вёрстка
  • списки и формы
  • интерфейс поверх игры

Canvas — одна растровая текстура в памяти GPU. Подходит для:

  • игры и частицы
  • плотная анимация
  • полный контроль над пикселями

SVG — вектор в DOM; удобен для диаграмм. Сложные сцены с сотнями узлов тяжелее Canvas.

Частый гибрид: UI на DOM, игровое поле на <canvas>. Подробнее — глава 7.


Чеклист чтения чужого кода

СтрокаСлой
x += vx * dtupdate, физика
if (keys.ArrowLeft) player.x -= 5ввод в модель
ctx.arc(x, y, 10, ...)render
gl.drawArrays(...)низкоуровневый API
state = 'MENU'конечный автомат

Порядок разбора:

  1. Найти главный цикл (loop, tick, Update в Unity)
  2. Выписать глобальные массивы (balls, entities, GameState)
  3. Отделить ввод (keyboard, mouse, touch)
  4. В update — движение, коллизии, спавн, удаление по флагам
  5. В render — порядок слоёв, save/restore, translate/rotate
  6. На первом проходе пропустить шейдеры, пулы и микрооптимизации

Признаки плохой структуры

  • рисование внутри update
  • изменение модели в draw (кроме чисто визуальной интерполяции)
  • координаты-магические числа без WIDTH/HEIGHT
  • мировые и экранные координаты без объекта camera
  • один файл на тысячи строк без drawX

Рефакторинг: сущности в классы, render — чистые функции (ctx, model).


Связи