DEV Community

Mario JGT
Mario JGT

Posted on

Devlog: capturing smooth game footage from a renderer that never hits 30fps

Hey guys 👋 Quick devlog on the side project.
I'm building an open-world stickman superhero game. Flat white surfaces, black outlines, no textures and no colour anywhere. The whole city is built from modules on a grid rather than baked meshes, which is the load-bearing decision of the project: destroying a wall is removing a module and building one is adding it back, so destruction and construction are the same system.
This week went into the landscapes, so I wanted a 20 second clip flying through a few of the districts.

The bit that was actually interesting

I wanted the footage captured out of the real game rather than reconstructed in an editor. The obvious approach is to drive it with Playwright and take a screenshot every frame, but that falls apart immediately: rendering under automation is far slower than a screenshot loop can keep up with, so wall-clock capture stutters and the timing drifts.
The fix is to stop letting the clock decide. Before the game boots, hijack requestAnimationFrame and queue the callbacks instead of running them:

  • replace requestAnimationFrame with a function that pushes the callback onto a queue- expose a step(dt) that advances a virtual timestamp and drains the queue- call step(1000 / 30) once per screenshotEvery captured frame now advances the simulation by exactly 1/30th of a second, whatever the renderer is actually doing. A frame that takes 300ms to draw and a frame that takes 8ms produce identical motion. The result is smooth 30fps footage from a renderer that never once hit 30fps, and it is deterministic — the same seed gives you the same clip every time. The same rig drives the camera: for the aerials it detaches the chase camera and dollies an external one between two framings, and for the traversal and combat shots it just feeds synthetic input to the real player controller. Nothing in the video is staged. ## Stack Three.js driven imperatively, Rapier for physics, React for the HUD only, TypeScript in strict mode, packaged with Tauri. Video's attached. Would love to know which district reads best — the citadel and the industrial yard are the two I'm least sure about.

Top comments (0)