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

Архитектура — модель, 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).


Связи​