Архитектура — модель, 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 * dt | update, физика |
if (keys.ArrowLeft) player.x -= 5 | ввод в модель |
ctx.arc(x, y, 10, ...) | render |
gl.drawArrays(...) | низкоуровневый API |
state = 'MENU' | конечный автомат |
Порядок разбора:
- Найти главный цикл (
loop,tick,Updateв Unity) - Выписать глобальные массивы (
balls,entities,GameState) - Отделить ввод (keyboard, mouse, touch)
- В
update— движение, коллизии, спавн, удаление по флагам - В
render— порядок слоёв,save/restore,translate/rotate - На первом проходе пропустить шейдеры, пулы и микрооптимизации
Признаки плохой структуры
- рисование внутри
update - изменение модели в
draw(кроме чисто визуальной интерполяции) - координаты-магические числа без
WIDTH/HEIGHT - мировые и экранные координаты без объекта
camera - один файл на тысячи строк без
drawX
Рефакторинг: сущности в классы, render — чистые функции (ctx, model).