← Каталог
Canvas — модель, update, render и игровой цикл
Минимальная 2D-игра: отдельные слои данных, физики, отрисовки и requestAnimationFrame.
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Модель → update → render</title>
<style>
body { font-family: system-ui, sans-serif; margin: 1rem; background: #0f172a; color: #e2e8f0; }
canvas { display: block; background: #1e293b; border-radius: 8px; margin-top: 0.5rem; }
code { background: #334155; padding: 0.1em 0.35em; border-radius: 4px; }
</style>
</head>
<body>
<h1>Шар на canvas</h1>
<p>Слои в <code>main.js</code>: <strong>модель</strong> → <strong>update</strong> → <strong>render</strong> → <strong>цикл</strong>.</p>
<canvas id="game" width="480" height="320" aria-label="Игровое поле"></canvas>
<script src="main.js"></script>
</body>
</html> <!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Модель → update → render</title>
<style>
body { font-family: system-ui, sans-serif; margin: 1rem; background: #0f172a; color: #e2e8f0; }
canvas { display: block; background: #1e293b; border-radius: 8px; margin-top: 0.5rem; }
code { background: #334155; padding: 0.1em 0.35em; border-radius: 4px; }
</style>
</head>
<body>
<h1>Шар на canvas</h1>
<p>Слои в <code>main.js</code>: <strong>модель</strong> → <strong>update</strong> → <strong>render</strong> → <strong>цикл</strong>.</p>
<canvas id="game" width="480" height="320" aria-label="Игровое поле"></canvas>
<script src="main.js"></script>
</body>
</html> /**
* Энциклопедия 4.18 — От чисел к картинке
* https://spirzen.ru/encyclopedia/4-code-dev/4-18-graphic-dev/1
*/
const canvas = document.getElementById('game');
const ctx = canvas.getContext('2d');
const W = canvas.width;
const H = canvas.height;
// ─── 1. МОДЕЛЬ (только числа в памяти, экран не трогаем) ───
const ball = {
x: W / 2,
y: H / 2,
vx: 140,
vy: 95,
radius: 18,
color: '#ef4444',
};
// ─── 2. UPDATE — меняем модель по правилам игры ───
function update(dt) {
ball.x += ball.vx * dt;
ball.y += ball.vy * dt;
const r = ball.radius;
if (ball.x < r || ball.x > W - r) {
ball.x = Math.max(r, Math.min(W - r, ball.x));
ball.vx *= -1;
}
if (ball.y < r || ball.y > H - r) {
ball.y = Math.max(r, Math.min(H - r, ball.y));
ball.vy *= -1;
}
}
// ─── 3. RENDER — читаем модель, команды «художнику» ───
function render() {
ctx.fillStyle = '#0f172a';
ctx.fillRect(0, 0, W, H);
ctx.fillStyle = ball.color;
ctx.beginPath();
ctx.arc(ball.x, ball.y, ball.radius, 0, Math.PI * 2);
ctx.fill();
}
// ─── 4. ИГРОВОЙ ЦИКЛ (~60 FPS) ───
let lastTime = 0;
function loop(timestamp) {
const dt = lastTime ? Math.min((timestamp - lastTime) / 1000, 0.05) : 0;
lastTime = timestamp;
update(dt);
render();
requestAnimationFrame(loop);
}
requestAnimationFrame(loop); /**
* Энциклопедия 4.18 — От чисел к картинке
* https://spirzen.ru/encyclopedia/4-code-dev/4-18-graphic-dev/1
*/
const canvas = document.getElementById('game');
const ctx = canvas.getContext('2d');
const W = canvas.width;
const H = canvas.height;
// ─── 1. МОДЕЛЬ (только числа в памяти, экран не трогаем) ───
const ball = {
x: W / 2,
y: H / 2,
vx: 140,
vy: 95,
radius: 18,
color: '#ef4444',
};
// ─── 2. UPDATE — меняем модель по правилам игры ───
function update(dt) {
ball.x += ball.vx * dt;
ball.y += ball.vy * dt;
const r = ball.radius;
if (ball.x < r || ball.x > W - r) {
ball.x = Math.max(r, Math.min(W - r, ball.x));
ball.vx *= -1;
}
if (ball.y < r || ball.y > H - r) {
ball.y = Math.max(r, Math.min(H - r, ball.y));
ball.vy *= -1;
}
}
// ─── 3. RENDER — читаем модель, команды «художнику» ───
function render() {
ctx.fillStyle = '#0f172a';
ctx.fillRect(0, 0, W, H);
ctx.fillStyle = ball.color;
ctx.beginPath();
ctx.arc(ball.x, ball.y, ball.radius, 0, Math.PI * 2);
ctx.fill();
}
// ─── 4. ИГРОВОЙ ЦИКЛ (~60 FPS) ───
let lastTime = 0;
function loop(timestamp) {
const dt = lastTime ? Math.min((timestamp - lastTime) / 1000, 0.05) : 0;
lastTime = timestamp;
update(dt);
render();
requestAnimationFrame(loop);
}
requestAnimationFrame(loop);