Simple football-like multiplayer game to explore basic multiplayer state synchronisation.
To get this working, I went through a couple milestones:
Players and Ball, keyboard input, physics for kicking, collision detection, scoring.
Added an Express + Websocket backend that simply echoes/broadcasts moves back to all players.
A POST is done first to join the game and get the player number.
Moves are then sent to the WebSocket and are echoed back.
Each player is running the game engine, and the server merely echoes players' moves to all other players, where the moves are applied to the current state.
This achieves basic synchronising of game state, for a little while. But things quickly get out of sync because the state that each input is applied to on the remote end diverges more and more from the state on the origin side.
- The server will also run its own version of the physics engine and run inputs on it just like the clients do.
- Each client sends all moves to the server, continuing to process local moves immediately.
- But now each client regularly receives messages that take the form of State updates, rather than individual remote moves. The server-provided state updates take precedence. This is roughly a prediction-based approach, see here, and here.
- The server receives moves from each client and applies them locally.
- The server runs two related loops - 1 to update the physics engine (rather rapidly), and one to broadcast the current game state (more slowly).
- Mouse/touch support
- Status bar with message output
- Latency display
- Observer mode (players > 2)
GitHub actions used to deploy the front-end to S3 and backend to ECS. CloudFront used to serve everything - static S3 content and API requests to container (wss WebSocket and HTTPS POSTs.) Lambda used to update the LB SG to restrict to CloudFront IPs.
terraform apply
to deploy it.