moves / game dev

Game dev

Game loops, input, collision, and sprites in plain TypeScript and Canvas.

Fixed-timestep game loop

game-looprequestanimationframephysics

Run physics in fixed steps and render as often as the screen allows. An accumulator carries leftover time between frames, so a 60 Hz and a 144 Hz monitor simulate the same game. Clamp the frame time so a backgrounded tab doesn't try to catch up on minutes of updates. Phaser, Godot, and Unity do this for you; write it yourself when you're on plain Canvas or a renderer like PixiJS.

Frame-rate independent movement

delta-timemovementgame-loop

Speeds should be per second, not per frame. Moving 4 px every frame means a 144 Hz player moves 2.4× faster than a 60 Hz one. Multiply by the elapsed time (delta time) instead. Good enough for simple games; use a fixed timestep when collisions or physics must be consistent.

Keyboard input without stuck keys

inputkeyboardevents

Track which keys are held in a Set and read it during update, instead of moving things inside event handlers. Use `e.code` (physical key) so WASD works on any keyboard layout. Clear the set on blur: if the player alt-tabs while holding a key, keyup never fires and the character walks forever.

Box collision (AABB)

collisionaabbphysics

Axis-aligned bounding boxes are the cheapest useful collision check: two rectangles overlap unless one is fully to the side of, above, or below the other. To resolve a hit, push the moving box out along the axis with the smaller overlap. Very fast objects can pass through thin walls between frames (tunneling) — use smaller steps or a physics engine like Rapier for that.

Sprite sheet animation on canvas

spritesanimationcanvas

Pack animation frames side by side in one image and draw one slice at a time with the 9-argument `drawImage`. Pick the frame from elapsed time, not a frame counter, so the animation plays at the same speed on every monitor.

Crisp pixel-art scaling

pixel-artcanvasscaling

Render at the game's native low resolution, then scale the canvas up with CSS. Turn off smoothing in both places, and scale by whole numbers — a 2.5× scale makes some pixels wider than others. Leftover space becomes letterboxing.

WWADD — Moves. Stacks. Judgment calls.

FREE REFERENCE · NO LOGIN · NO TRACKING