Once upon a time I got a job interview task of coding the "snake" game, the result was a nice one (github, codepen).
Then I thought, what would it be to convert it into an online multi-player game, using node.js and WebSockets? let's see…
I started to think about how I wanted to implement the game, and the first question was "who controls the game"? do we put all the game management and business logic in the client, and use the server just as a hub for broadcasting messages? or do we let the server control the game and the client just draw what the server says.
Set "cheating" aside, implementing everything in the client was much more simple, as I already had a working snake game… but… that isn't really an online game, so I decided to let the server be the king.
But, if the server controls the game, it means the snake (on the client) can't move until the server told it so, and if the player wants to change the snake direction she has to wait for the server's response before it will happen, this could lead to a very laggy game…
After reading about the concepts of "client-side predictions" and "server reconciliation" (here) I decided to start with a "simple" game, meaning a game that would work perfectly over LAN, and will be OKish over WAN, I believe there is still a lot to learn by doing so, and adding advanced concepts could be done later.
So… you can play the game on Heroku, the lag is obviously apparent, but not that bad…
The SnakeMatch is a regular "snake" game where player1 competes with player2 for Pellets, each match is for 60 seconds and the player who collected more pellets wins. Of course that the regular Snake rules apply (a snake can't collide with itslef and can't hit the wall).
The game is built from the following "game objects":
As we said, this is a fairly simple game, the server is responsible for managing the game, and the client is responsible for rendering the game state and send commands to the server.
Below is a schema of a game flow:
And here is a diagram with the main classes in the client and server:
The protocol determines how messages between the client and server will look like, my first thought was to simply use json, however, there are two issues with json that bothered me:
var updMessage = {
type: 5, // Message type
timeToEnd: 53, // Time to game end
directions: [ '6', '4' ], // The directions each snake is heading
sizes: [ 6, 6 ], // The snake sizes
pellets: [ 34, 21, 67, 54 ], // The cell indices where we have pellets
score: [ 6, 5 ] // The players score
};
var encoded = JSON.stringify(updMessage); // encoded.length = 100
On the other hand, using a custom protocol, we would get the following string:
var encoded = '5#53#6,4#6,6#34,21,67,54#6,5'; // encoded.length = 28
Performance wise, JSON.stringify
is 83% slower, that is quite a difference, especially if we would want later to increase the update rate from 10/sec to something like 30/sec…
OK, enough talking, in part 2 we will dive into the code…