This is the first time I've done realtime multiplayer outside some coding experiments. It's not a topic I know much about, so I kind of figured stuff out from first principles.
As I see it, the main issue is how to keep the game state synchronized. My approach is to have a copy of the game state on each client, and use the server as a pretty simple timekeeper and relay.
When a client wants to send a command like "move this airship there", it sends this command to the server. The server sends out timed updates that contain all commands that arrived during the last time slice. Clients then receive these updates and execute them at a particular point in time.
The server also provides the random number generator seed. This means that the game state on all clients has the same starting conditions and the same inputs over time, and is hence in sync.
The advantage of this approach are that it's simple to implement, as most of the game code doesn't have to care about multiplayer. The disadvantages are that there is no easy way to detect or reconcile sync errors if they do happen, and the response time is kind of slow, as commands have to do a full round trip to the server before they can be executed. And in practice, the clients want to keep a buffer of server updates to ensure that they don't have to stop advancing game time from a lack of updates, which increases the lag even further.
Thankfully, the airships game is not super-hard-realtime: it's not unrealistic for a command to take a fifth of a second to be executed. And in practice, this approach works!
So what's up next? Well, there's still some tidying up to be done on multiplayer, like dealing with disconnects. After that, the major to-do items are:
- Lots more module types including the ability to make buildings and land vehicles
- Varied landscapes to fight over (hills and trees to crash into)
- The (fairly simple) single-player strategic game, which I'll lay out in some detail in the next post