Skip to content
Ayotl

← All notes

October 12, 2026 · In War Zone

War Zone: the grenade that seemed to slow down mid-air

“On long, high throws the grenade sort of slows down.” The game wasn't slow: with the CPU throttled six times it still ran at 30 frames a second. What was braking was the camera.

The complaint arrived just like that, with a “sometimes” and a “sort of”. The first step was ruling out the obvious: the real game ran in Chrome, with its own loop and the CPU throttled four and six times, like a mid-range and a low-end phone, throwing the longest, highest grenade the castle allows. Thirty simulation ticks per second, and not a single frame above 33.5 ms. The game wasn't slowing down.

So the thing the player sees was measured instead: the grenade's speed in screen pixels, frame by frame. There it was. On release the camera zoomed out from 2x to 1x and centred itself between the thrower and the grenade, chasing it with 12 to 15 % smoothing per frame. All three subtract: zooming out halves the grenade's size and speed, following it eats half of its motion, and since the camera arrived late, the grenade left the frame at the top.

tick   pantalla (x, y)   px por cuadro
   6      143,  39            6,4
  12      144,  16            2,6
  18      142,   8            0,7   <- ya detrás del marcador
  24      143,   8            0,4
  36      153,  13            1,4
The same throw, before: from 6.4 down to 0.4 pixels per frame, and almost a second out of frame.

The fix wasn't following it better but not having to follow it. The simulation is deterministic and doesn't depend on the camera, so the whole flight is known the moment the shot leaves: a copy of the projectile is simulated with the same physics, without touching the world, and the camera frames the entire path from the first frame. It barely moves, and the grenade crosses the screen. If the flight doesn't fit even at 1x, the camera goes along with it on the very frame it nears the edge, with no lag.

/** Lo que le queda por volar, con la misma física y sin tocar el mundo. */
vueloRestante(p, n = 240) {
  const c = { ...p }, pts = [];
  for (let i = 0; i < n && c.viva; i++) {
    const fin = this.pasoProyectil(c, false);   // false: nada estalla de verdad
    pts.push({ x: c.x, y: c.y });
    if (fin) break;
  }
  return pts;
}
The same throw now moves at 2 to 6 pixels per frame, and is visible all the way.

The same measurement turned up another bug that had also been reported as something else: “when the camera goes off the map there's a distortion”. The map limit was applied to the camera's target, not to the camera: while the zoom opened near the right or bottom edge, the target moved inwards and the smoothed camera arrived late. The view overshot the map by up to 22 pixels, nothing was drawn there, and the canvas kept the previous frame: streaks. In the cave level it happened in 39 % of frames. Now the camera is clamped with the zoom of that very frame, the sky and sea are painted beyond the map too, and it only peeks outside, 48 pixels at most, to follow something that really leaves: a bomb going over the edge or a stick figure falling into the void.

And a third one, as a bonus, while looking at the castle complaint (“it turns into a long-range grenade battle”): the pickaxe, the tool for clearing a path, never let anyone through. It dug radius-5 circles starting 4 pixels from the hand, which left a pixel of earth at the tunnel's mouth, at the feet and at head height of a stick figure 10 pixels tall. No test walked through the tunnel after digging it. Now one does, at 0°, ±20° and 35°, and the castle also has a gate running through it.

All three complaints were true, and all three described something else. What told them apart was measuring what the player sees, rather than what you believe the code does. War Zone 1.0.6 is playable at dailychallenge.click/warzone.

All notes