No canvas, no library โ just a fixed-position emoji and vanilla physics
The canvas version renders into a WebGL overlay using
KAPLAY. This version skips all of that: the fox is a plain <span>
with position: fixed, and physics is a requestAnimationFrame
loop that reads getBoundingClientRect() every frame.
No dependencies, no build, ~120 lines of JS. The ledge-extraction algorithm is the same: scan every element, extract top edges, merge overlapping intervals at the same Y-level into thin shelves.
No KAPLAY, no canvas, no CDN. Runs from file://.
The fox is an actual element โ inspectable in DevTools.
Platforms re-read on every scroll and resize event.
Because the buddy is position: fixed and platforms come from
getBoundingClientRect(), both live in viewport coordinates.
Scrolling shifts the DOM elements relative to the buddy โ platforms move
and the fox responds in real time.
WebGL overlay via KAPLAY. Full physics engine. Easy sprites and animations. Heavier โ needs CDN.
Fixed-position element. Manual physics loop. No deps. Buddy is a real DOM node.
| Property | Canvas | DOM |
|---|---|---|
| External library | KAPLAY (CDN) | none |
| Rendering | WebGL | CSS transform |
| Buddy node | virtual (game object) | real DOM element |
| Physics | KAPLAY engine | manual rAF loop |
| Interaction | KAPLAY events | DOM events |
Each frame the loop computes the buddy's previous and next bottom edge and checks whether they straddle a platform's top. If they do, the buddy snaps to the surface and vertical velocity zeroes out. There are no side walls โ only top-edge shelves โ so the fox can never get wedged between elements.