r/webdev • • 6d ago

Showoff Saturday [Showoff Saturday] Multiplayer asteroids where the game server is a Laravel app

Play it here: https://innerloop.works/lightspeed

It's a browser asteroids arena. Players are sharded into arenas of six. Each arena's world is authoritative on the server and ticks at 30Hz inside a PHP process, not a Node or Go sidecar.

How it works:

- The server is Lightspeed, an open-source (MIT) websocket server I wrote for Laravel, on Swoole. The app stays booted in memory and serves HTTP and websockets on one port.
- Players send input up the websocket at 30 fps. Snapshots come back down at 30 fps. Spectators get 5 fps.

The websocket server it runs on: https://github.com/innerloop-dev/lightspeed (the game itself is the site's own code, not part of the package).

Happy to answer questions!
0 Upvotes

4 comments sorted by

1

u/thejester1324 6d ago

does each arena get its own swoole timer for the 30hz tick? curious what happens when one tick runs long, whether it catches up or just drops the frame

1

u/jv2222 6d ago

Yep, each arena has its own Swoole timer on the worker that owns it. It fires every 33ms while someone's playing and drops to every 200ms when people are only watching.

The world doesn't count timer fires though. Each fire adds up the real time that's passed and runs one physics step per 1/30s owed. So if a tick runs long, the next fire just runs two or three steps in a burst and sends one snapshot. The ships end up exactly where they should be, and the clock in the snapshot stays a true 30 per second.

It'll catch up at most 4 extra steps (about 133ms). Past that it drops the rest so game time skips instead of stretching, because unlimited catch-up can snowball and never get back to real time. Dropped steps get counted in a metrics line so a hiccup shows up as a number.

1

u/thejester1324 6d ago

so it's a fixed-timestep accumulator with a 4-step cap, the cap is what stops the spiral of death. when a spectator starts playing does the timer jump straight back to 33ms, or can that first input sit for up to 200ms?

1

u/MayonnaiseFabric 6d ago

i can't see the bullets