Skip to main content

Indie game storeFree gamesFun gamesHorror games
Game developmentAssetsComics
SalesBundles
Jobs
TagsGame Engines

Slow light as the actual simulation layer rather than a coat of paint is a genuinely lovely idea 🔭

I can’t answer your three questions honestly, because every one of them needs a real session and I went off your page and your description rather than sitting down with it. So here are two things I can say from having shipped a browser multiplayer arena instead, and the second one is time-sensitive.

The intentional ping delay is the risky one. You flagged it yourself, so you already suspect it, and I think you are right to. The problem is not whether the tutorial explains it. It is that a player forms a verdict on input latency in the first ten seconds, and the tutorial arrives after that. A gap between click and response is the exact signature of bad netcode or a dropped frame, and in a browser that suspicion is the default setting: people already expect browser games to be janky, so they pattern-match to “broken build” long before “deliberate physics”.

The fix is not more explanation, it is making the delay visible as travel. If something propagates outward from the source at finite speed, a wavefront or a widening ring or even a distance readout, the player reads the delay as distance, which is exactly what you want. If the unit simply responds late, they read it as lag. Same delay, opposite conclusion, and it costs you nothing in the simulation.

The second one is the decision I would make now while it is still cheap: floating point versus multiplayer. You said multiplayer is a long-term goal. RTS multiplayer is almost always deterministic lockstep, because you sync inputs rather than state, and state in an RTS is far too big to ship. Lockstep needs every client to compute bit-identical results forever. And in JavaScript, Math.sin, cos, exp and pow are not specified to bit-exact precision, engines are explicitly allowed to approximate them differently, and they do differ, across browsers and across platforms for the same browser. Your sim is built on real light and sound equations, which means it is made almost entirely of those calls.

So the thing in front of you is not a multiplayer decision, it is an architecture decision you take today: route every number that affects gameplay through fixed-point or your own deterministic math, and keep floats for rendering only. Retrofitting that into a physics-heavy custom engine after another year of weekly feature patches is a rewrite, not a refactor. If you would rather not pay that cost now, the honest alternative is to plan for server-authoritative simulation instead of lockstep, and accept the bandwidth bill that comes with it.

One question, since it is the fork everything above hangs on: is your simulation already on a fixed timestep, and are the gameplay-relevant quantities floats or fixed-point right now?

(1 edit)

Thanks for the input! In actuality, the slow light is the coat of paint (the renderer), the simulation layer happens in a true-state layer that is hidden from players (but observers watching a game can toggle it on) - there are also some abilities in game that show the true-state. It follows real physics because the dynamics is Newtonian (no relativistic effects since we're operating far from the speed of casaulity which is light speed in a vacuum). In my game, light is slowed down to 1/10th the speed of sound via a ficticious atmosphere with an enormous index of refraction.

As for your other concerns, yes I agree the ping needs to be visible and it indeed is a faint arc visible emitted from command structures and connected relays. I can probably add a toggle to adjust opacity and brightness of it since it can be a bit annoying if you have high APM!

For multiplayer, the game would simply update the true state to everyone's backend and then compute the delay perception locally. The way it works is that all entities in the game have vertices (most units store 4 position coordinates (corners of the sprite) but larger units can have more) which carry history information which is updated every 0.05 seconds (the sim tick rate is 20 Hz). Basically, there is a large ring buffer for all vertices that is precomputed to the length of the maximal delay (which is the map diagonal divided by the speed of light, or about 30-45 seconds roughly). And every vertex stores state information such as HP, position, alive/dead flag, ammo counts, buff/debuff flags, etc. This is how the magic happens and how you can see the past in a dynamic way since the backward light cones of all your units calculates the earlier states as needed for everything by using a delay field calculated over the entire map.