A devlog by Neeraj Kotwani, who builds every game on Elipar.
A player told me that in Neon Serpent, after you eat the first orb, no more ever appear. That is a specific, confident bug report, and it sent me straight to the spawn function.
The spawn function was perfect. A test ate six orbs in a row and the game placed a new one correctly every time. The orbs were spawning. The player simply could not see about a third of them.
The camera was cropping the arena
The camera distance was a hardcoded number — 15.5 in portrait, 13.5 in landscape — with a comment saying it was "pulled closer so the arena fills the frame." It filled the frame by overflowing it.
The measurement is easy once you think to make it: take all 225 cells of the grid, project each one through the live camera, and count how many land outside the visible range. 72 of them did — the entire left and right columns — reaching 1.73 on an axis where anything past 1.0 is off-screen.
Food spawns on a uniformly random empty cell. So roughly one bite in three put the next orb somewhere invisible, and the player hunted for food that was genuinely on the board, then died against a wall. From inside the game that is indistinguishable from "no food came."
The fix is to compute the distance instead of choosing it: project the arena's extreme corners, measure how far the worst one falls outside the viewport, scale the distance by that, repeat. It is near-linear, so it settles in one or two passes. Verified at six viewport sizes including the real portrait frame: 0 of 225 cells off-screen.
This was the fifth time
What makes this worth writing up is that I had already made the same mistake four times, in four unrelated games, each time in a way that looked like a different problem.
Dots & Boxes 3D overflowed its board off both side edges in portrait. The trap there is an intuition: the horizontal field of view at a 3:4 aspect is much narrower than the vertical one suggests, so a camera that frames correctly by height quietly cuts the sides off. Fitting to whichever axis is actually tighter is the whole fix.
Curling 3D was the strangest. The computed camera-to-house distance came out at about 29 world units. The scene's fog started cutting off at 30. So the house rings — the single most important thing to see in a curling game, the thing you are aiming at — were fogged to almost nothing. Nothing was wrong with the camera or the fog in isolation; two independently reasonable numbers had landed on top of each other.
Chess 3D taught me the subtlest version. At the original elevation the board projected far wider than tall, so the horizontal axis bound the fit and the board used only 26% of the frame. Obvious answer: tilt the camera steeper. So I swept the elevation and measured.
On a wide desktop frame, steepening bought nothing at all — coverage went from 40.7% to 39.6%, flat — while the height of a king on the player's own back rank collapsed from 89 pixels to 27. Steeper made the board no bigger and the pieces you are actually moving four times harder to read. On a tall phone frame the same sweep showed real gains, 34.5% up to 56.6%.
Two metrics, opposite conclusions, depending entirely on the shape of the window. So the elevation follows the aspect too: shallower on wide frames, steeper on tall ones. I would never have found that by looking at it, because on a desktop monitor both versions look fine.
Neon Dash 3D was a variant of the same habit in two dimensions: its background grid was drawn from a vanishing point at the middle of the canvas, while the road's real horizon sits at 40% of the height. Two different points, which is why those lines fanned diagonally across the road instead of receding into it.
Why a hardcoded number always feels right
Every one of these started the same way. You position a camera, you look at it, you nudge the number until the shot looks good, and it does look good — on the window you happen to have open. Then it ships into a 3:4 phone frame, a square frame, a rotated frame, a fullscreen landscape frame, and the number that was tuned for one shape is wrong for all of them.
And crucially it fails silently. Nothing throws. There is no error, no warning, no visual glitch — just content quietly outside the viewport. A screenshot at the size you tuned it for will pass forever.
The part worth taking away
Two rules, and they have held for five games:
Frame from the aspect ratio, never from a tuned constant. Solve for the distance that fits the scene's real extent in whichever axis is tighter, and recompute it on every resize.
Assert on projected bounds, not on a screenshot. Take the points that must be visible — every grid cell, the board's four corners, the goal — project them through the live camera, and assert every one lands inside the viewport at several real frame sizes. It is a handful of lines and it is the only check that catches a crop, because a cropped scene still renders a perfectly attractive picture of the part that survived.
There is a third, softer lesson in the Neon Serpent report. The player described a symptom in terms of the mechanic they could name — food spawning — and the actual fault was two systems away, in code with no connection to spawning at all. Reproduce and measure before you accept the diagnosis that comes with the bug report, however confident it sounds. That report was accurate about the experience and wrong about the cause, which is the normal case, not the exception.
All five are free and instant in a browser: Neon Serpent, Dots & Boxes 3D, Curling 3D, Chess 3D and Neon Dash 3D.