Multiplayer gaming, part 1: Sync the future!

Last year I was writing a little game intended to be run in the browser. I was writing it in pure javascript (i.e. no graphics or whatsoever was stored, everything was dynamically generated) for the js13k Games 2013, it is the Untitled 13 (can be played here).

One of the base concepts was to build a multiplayer game. It was challenging despite I’ve written some basic games, also mulitiplayer ones, I’ve never tried to write a real-time strategy game yet (not counting a quick POC). The synchronization of the game between players was the most interesting part of it, and therefore my favorite one. I was not intended to sync the whole game state (map, objects, internal states, etc.) continuously as this can easily become a huge set of data even for tiny games at high refresh rates so I decided I will come up with a better, more resource-friendly solution.

I’ve been thinking about the game: it has some mechanics, player events events and also their effects on the gameplay and concluded one could be separated from the other – of course it turned out that I was not the first who came up with this approach. So instead of syncing everything, I was thinking about synchronizing just the map in its starting state and a list of events.

All these events were always originated from the players (i.e. buy an item, toggle a switch) or from the game mechanics (i.e. an enemy is close enough to be fired on, an object loses health, objects collide). As the game on both ends are always identical the result of mechanics should be always identical too, therefore all I left to deal with were the events from the players.

So basically all I was doing is this: my game had so-called “ticks” that were the updates for the game internal states (this event was happening with a guaranteed interval, i.e. 15 times per seconds, or if late (due to lack of CPU resources or bad timing) all the affected ticks ran anyways to catch up), and when a player did an action (i.e. clicked a switch) I stored a record in a queue about it and a “process this on the nth tick” property. I’ve also sent this record over the network to the other player. This way I introduced a slight delay (this nth tick was always about 300 milliseconds in the future) but during this delay I sent the event to the other player and when the nth tick came both players made the change on their isolated environment in the exact same moment (speaking in game time) and therefore both ends have seen the same new state, the game is deterministic.

Later I’ve learned – in a Gaffer on Games post and in another one about network programming in Age of Empires (both are must reads!) – this is a so called simultaneous simulation approach with one big difference. The handling of the lag on the network. This was the worst thing during the development and tests of the game. As I’ve been syncing future events if the notification got stuck somewhere between the players it could easily come later than it must have been executed. As the tick it was intended to be run at was passed (and the other player have executed at that time) the game became out of sync. And this is bad, really bad. (I’ve made some efforts to handle this, but these turned the game code much more complicated, i.e. to be sure that important events happen on both sides I added them as an event to the queue (and sent that over the network), that’s why the little creatures pause for a while before exploding at the target markers. But this is bad, don’t do this. Keep reading for a simpler solution instead.)

In a real simultaneous simulation the players should be aware of the lag in the propagation of events so instead of just saying “here, run this on the nth tick” there needs to be a “I have nothing for you to run on the nth tick, carry on”. And if the other player does not specify what to do (or not to do) on the nth tick when it comes the simulation should pause while it is unsure about what to do. Which is not nice but far much better than becoming out of sync. Obviously working with 15 ticks per seconds and expecting the network to transfer the data for the next tick is nearly impossible (talking about transmitting over the internet as this would permit about a 66 milliseconds deadline on a client1-server-client2 route, also sending at least 15 events every second) and would result frequent pauses, and that would be really annoying. So instead of scheduling events for any tick of the game a rule should be applied to limit the ticks that can accept events. Saying events can be scheduled only for every 5th ticks reduces the count of transmitted packets dramatically, also extends the deadline to a more sane value.

Also, when a pause occurs due to network lag the rule of scheduling could change i.e. not every 5th but every 10th tick should accept events. And likewise when the network seems reliable for a long time this number could decrease.

But this topic will be covered in another post, first I’ve to try this approach. Although I think this should work nicely as games like Age of Empires and Warcraft used this method pretty reliably.

Recommended reading:

r42.cc

Lately I’ve been designing some little PCBs and thought it would be nice to add a short URL on it leading to a page about that particular PCB (or PCB series in the future). Also, adding the short URL to any other things I (or we, as a little maker team with a few of my friends) create. Although this will probably not have any sort of impact on the early designs (made in just one copy), it’d make them more personal, I guess.

So I had to come up with a short domain name – I already have one but that is under the .hu TLD – that gives away something about the purpose of itself… It was ridiculously challenging to find one that is not already taken in the .com/.org/.cc world. In the end I’ve chosen the r42.cc. The first part stands for revision42, something that is probably reached by a successful project (and of course, 42 is the answer), and the cc stands for creative community.

So if I put here some photos and designs in the future you should check it for this URL and open it to see some related content.

Random Idea: Moving Munzees

I’ve been playing Geocaching for a while now.

Lately I’ve started to play Munzee, a game that is the little brother of Geocaching in my point of view. It is working by the same idea, you’ve given the coordinates and you have to find the hidden treasure. Although here is no treasure at all, just a QR code stuck to a surface – usually at the back of (traffic) signs and bottom of traffic lamps. So finding it is not that great challenge after a while…

The idea is the following: what if we stuck the QR codes on non fixed objects, but moving ones? I.e. you could stick it on a train (somewhere hidden, not on a window or seat, so where you could only find it if you’re looking for it). It would be more challenging, and also you could track where the object travels (could be illustrated on a “spotted here” map) also you could meet something you met earlier at a different place.

I think this could add another layer of fun to the game.

Logic Analyzer

Recently I’ve been playing around with some GameBoy hacking including its hardware – posts will come about this.

Before that I’ve had some work with communication between ICs and other devices and always had the feeling that development/troubleshooting would be far much easier if I could see the actual data transfers.

Unfortunately putting some LEDs around the wires is not always an option as the clock speed might be too fast to see them – of course when I program the master device I give the clock and mostly that could be slowed down, but in any other case seeing a LED blink at 4 MHz for example is not really for the naked eye.

So finally I made the decision to buy a logic analyzer. I found an 8 channel logic analyzer running at 24 MHz, that means I can sample 8 channels for logic high or low voltages at an interval of 41.67 nanoseconds, which is really cool. Fortunately enough the software part has a list of decoders where I can specify the purpose of each pin and the software automatically decodes and shows the actual data on each clock.

I’ll be back with more posts with this little analyzer guy soon. (Hopefully not Blizzard soon.)

Game Boy: my first steps

On 4th March, 2013 I bought a Game Boy Color in really good condition, so this became my very first game console (at age 27, huh).

On this day I heard the welcome notes for the first time – it felt great, hehe.

It says “© 1998 Nintendo” on the back, so this is a 15 years old platform (actually mostly a 24 years old with some improvements, as the original Game Boy was released back in 1989), but still great! I’m in love with it.

I’ve also checked out the Game Boy Advance (GBA) before I bought decided to go with GB/GBC line – the GBA has a 32-bit CPU at 16 MHz and 288 kB RAM + 96 kB of VRAM, this spec is just ridiculously high, who needs this much anyways? I’m sticking with the lower specs.

So I am now very happy with this little Game Boy Color – next thing on my TODO list to buy a programmable cartridge and start to test my developments outside the emulator.

This post was migrated and edited a bit from my old blog where it was posted on 1st April, 2013.