Creating Realtime Multiplayer Games using Node JS

A few months ago at work, we decided to build a realtime multiplayer game for the web, and we chose to go with Node.js for our multiplayer server.
It was a pretty strong success, and was up running for several months without a single crash or restart of the Node.js process.

We decided to write our game in Node.js because we had heard of this cool platform and had been itching to use it for a while. This turned out to be a blessing because it was very easy to get into, and many interesting Node.js libraries exist to help accomplish various task. A side benefit of using node is that javascript itself is very easy to use. This allowed us to focus on the problems all realtime network games face with less fussing with the constraints or compile times of less dynamic languages.

Node.js was also very lightweight on our servers even during peek usage. On our game the node.js process was using only 1 thread and ran at about 3-4% CPU usage running 8-10 simultaneous games each with their own collision engine instance.

The main problem

With this approach is that you cannot trust the users to give you correct information about where they are. A user would just tell you that they are everywhere, and they’ve hit everything and have 100% health at all times.

Another problem with this approach is that you can never represent the true motion path of an object.

This is sometimes called the ‘bouncing ball’ problem. It is caused by extrapolating the position based on the current velocity of an object until a new update is received, and then adjusting the position and velocity and extrapolating from that point until the next update. When the ball is at the apex of its parabola, the velocity is zero so when extrapolating, the ball will just appear to be stuck in the air until it suddenly appears to crash downward.

Finally yet another problem with this approach is packet loss. If one packet as shown by the dotted lines is dropped, the user will travel along an incorrect path for a longer period of time. OF course this time is measured in milliseconds, so it’s not the end of the world. However in action it feels wrong visually, because things don’t change position instantaneously in real life.

A Different Approach – The client/server model

During the course of development on the game we decided to take a look and see how it was generally done. After all people have been making realtime multiplayer games for a while now. We found some interesting sources of information, specifically the freely available Quakeworld source code, and some white papers from Valve.

In this approach there is a single authoritative server which is playing the game, and clients send only their sampled input input data. For example, I send only the fact that my spacebar key is being pressed down, and the server decided what that means in terms of the game. With this model we completely sidestep many problems of the previous implementation.

Rendering the world

Our nervous system is to work around latency. If we apply a small constant smooth latency to an object it is easy for a human being to adjust.
The key element of the puzle is that we render all clients N milliseconds backwards in time at all times. This is an arbitrary number, so I will use 75 for my example.

The key component

First we setup a system in place where the client recieves high fidelity updates from the server at discrete invervals.

We store WorldUpdates in an array.

When it comes time to draw the players on the scree, we simply draw them at `currentTime-interpAmount`

Each render, we first find the two updates that our render time falls between with a simple loop.

Once we find those two updates, we use a linear interpolation function to position our object precisely along it’s path.

If a packet is dropped, for example if we never recieve packet 343 on this slide, we can still render between two known packets 342 and 344

RealtimeMultiplayerNodeJS

We’re strong believers in open-source, and decided at the end of our development to clean up our code a bit and release it as an open-source project. Because we’re not good at naming things, we named it RealtimeMultiplayerNodeJS.

RealtimeMultiplayerNodeJS is a framework specifically for building HTML5 multiplayer games with the Client / Server model. In this model, connected users send only input and the game itself runs on the server.
Clients are interpolate between two known world snapshots based on the current synchronized time.

How to use

Browse to ‘/DemoHelloWorld.html’ (Note the file must be viewed from a server in order for the websocket to connect)

Physics Demo:

This demo uses a Box2D.js implementation to create a world, and show’s off the idea of synchronized physics, and taking advantage that all the simulation happens on the server.
It also shows synchronized interaction between multiple users, and an example of sending a message to the server which it interprets back into the game.

DemoHelloWorld:

The most basic interesting working demo we could come up with. Objects move from left to right.

DemoCircle:

A demonstration of the engine’s simple CircleCollision engine, which can provide you with simple collision information and fires an event when two objects collide with the two objects.
This demo also shows one implementation of having a special kind of entity which is controlled by the keyboard from a connected user. A character controlled entity

Finally, just to reiterate the point here is the entity interpolation chart in ANSCII form:

I had a few people say that they opened the file and nothing happened, the websocket doesn’t need it – but the page can error out due to not being displayed “off a server” and attempting to load some of the files. So I just added it as a step, but you’re right it’s not relient on that 🙂

I have problems in synchronisation of the bouncing balls at clients side. I have a single multiplayer game where the logic is on server side. When creating the balls, I can’t render them, I don’t know how, I am new to this stuff. Any ideas guys??