Subchapter 178.3
references/basics.mdMarkdown11 KBView on GitHub
A comprehensive reference covering web game development technologies, game architecture, and the anatomy of a game loop.
Sources:
<canvas> element. Suitable for 2D games, sprite rendering, and pixel manipulation.The modern web platform supports a full range of game types:
Every game operates through a continuous cycle of steps:
Games may be event-driven (turn-based, waiting for player action) or per-frame (continuously updating via a main loop).
window.main = () => {
window.requestAnimationFrame(main);
// Your game logic here: update state, render frame
};
main(); // Start the cycleKey points:
requestAnimationFrame() synchronizes callbacks to the browser’s repaint schedule (typically 60 Hz).;(() => {
function main() {
window.requestAnimationFrame(main);
// Game logic here
}
main();
})();;(() => {
function main() {
MyGame.stopMain = window.requestAnimationFrame(main);
// Game logic here
}
main();
})();
// To stop the loop:
window.cancelAnimationFrame(MyGame.stopMain);requestAnimationFrame passes a DOMHighResTimeStamp to your callback, providing timing precision to 1/1000th of a millisecond.
;(() => {
function main(tFrame) {
MyGame.stopMain = window.requestAnimationFrame(main);
// tFrame is a high-resolution timestamp in milliseconds
// Use it for delta-time calculations
}
main();
})();At 60 Hz, each frame has approximately 16.67ms of available processing time. The browser’s frame cycle is:
requestAnimationFrame callbacksThe simplest approach when your game can sustain the target frame rate:
;(() => {
function main(tFrame) {
MyGame.stopMain = window.requestAnimationFrame(main);
update(tFrame); // Process game logic
render(); // Draw the frame
}
main();
})();Assumptions:
For robust handling of variable refresh rates and consistent simulation behavior:
;(() => {
function main(tFrame) {
MyGame.stopMain = window.requestAnimationFrame(main);
const nextTick = MyGame.lastTick + MyGame.tickLength;
let numTicks = 0;
// Calculate how many simulation updates are needed
if (tFrame > nextTick) {
const timeSinceTick = tFrame - MyGame.lastTick;
numTicks = Math.floor(timeSinceTick / MyGame.tickLength);
}
queueUpdates(numTicks);
render(tFrame);
MyGame.lastRender = tFrame;
}
function queueUpdates(numTicks) {
for (let i = 0; i < numTicks; i++) {
MyGame.lastTick += MyGame.tickLength;
update(MyGame.lastTick);
}
}
MyGame.lastTick = performance.now();
MyGame.lastRender = MyGame.lastTick;
MyGame.tickLength = 50; // 20 Hz simulation rate (50ms per tick)
setInitialState();
main(performance.now());
})();Benefits:
// Game logic updates at a fixed rate
setInterval(() => {
update();
}, 50); // 20 Hz
// Rendering synchronized to display
requestAnimationFrame(function render(tFrame) {
requestAnimationFrame(render);
draw();
});Drawback: setInterval continues running even when the tab is not visible, wasting resources.
// Heavy game logic runs in a background thread
const updateWorker = new Worker('game-update-worker.js');
requestAnimationFrame(function render(tFrame) {
requestAnimationFrame(render);
updateWorker.postMessage({ ticks: numTicksNeeded });
draw();
});Benefits: Does not block the main thread. Ideal for physics-heavy or AI-intensive games. Drawback: Communication overhead between worker and main thread.
;(() => {
function main(tFrame) {
MyGame.stopMain = window.requestAnimationFrame(main);
// Signal worker to compute updates
updateWorker.postMessage({
lastTick: MyGame.lastTick,
numTicks: calculatedNumTicks
});
render(tFrame);
}
main();
})();Benefits: No reliance on legacy timers. Worker performs computation in parallel.
When a browser tab loses focus, requestAnimationFrame slows down or stops entirely. Strategies:
| Strategy | Description | Best For |
|---|---|---|
| Treat gap as pause | Skip elapsed time; do not update | Single-player games |
| Simulate the gap | Run all missed updates on regain | Simple simulations |
| Sync from server/peer | Fetch authoritative state | Multiplayer games |
Monitor the numTicks value after a focus-regain event. A very large value indicates the game was suspended and may need special handling rather than trying to simulate all missed frames.
| Approach | Pros | Cons |
|---|---|---|
| Simple update/render per frame | Easy to implement, responsive | Breaks on slow/fast hardware |
| Fixed timestep + interpolation | Consistent simulation, smooth visuals | More complex to implement |
| Quality scaling | Maintains frame rate dynamically | Requires adaptive quality systems |