Building a multiplayer projector game controlled with iPhone/iPad via node.js, socket.io and canvas

Published on Feb 14, 2013

I wanted to experiment with node.js, canvas and a whole bunch of other cool stuff for some time now but never really got to it. For the past four years or so, since I moved to Mechelen, we've had weekly meetups at my office or at a friend's place every thursday night. We hang out, talk about the latest tech or watch a movie.

To make these evenings a bit more interesting I decided to hook up a projector and build a game that we could play from the couch with two players at the same time. For the controllers I've decided that it would be cool to use our phones.

Here's a short recap of what I did.

HTML5 canvas for the simple game

The HTML5 canvas element is really not that hard to get started with as it might seem at first. Look at it as a simple blank canvas where you can draw stuff on by using Javascript. The code sample below is a little snippet that draws the ball in the game. To animate things on the canvas, a setInterval() function is called every X milliseconds to completely redraw the canvas. That way, we can use variables to dynamically set the X and Y position of where to draw the ball. If we move that position around every time setInterval() is called, the ball will appear to be moving on the canvas. Pretty simple, yet pretty sweet.

var canvas = document.getElementById('yourCanvas'); 
ctx = canvas.getContext('2d'); 
ctx.beginPath(); 
ctx.arc(75, 75, 30, 0, Math.PI*2, true); 
ctx.closePath(); 
ctx.fill();

If you want to animate/move the ball created with the code above, all you need to do is wrap the drawing code in a setInterval() function and change the X and Y coordinates (75 and 75 respectively in the example above) into variables. The complete code could look somewhat like this:

var canvas = document.getElementById('yourCanvas');
ctx = canvas.getContext('2d');

var X = 0;
var Y = 0;

function moveBall()
{
  ctx.clearRect(0,0,400,200); 
  ctx.beginPath();
  ctx.arc(X, Y, 30, 0, Math.PI*2, true); 
  ctx.closePath();
  ctx.fill();
  X++;
  Y++;
}

setInterval("moveBall()", 50);

Here is a good tutorial to get you started with the canvas element.

Gameplay

Use QR codes to get the party started

It's pretty cool to just project your game on a wall or even a building and have somebody scan the projected QR code to join in. This was actually the easy part. I just took a random QR code generator and used it to point the device to player1.php or player2.php, depending on which code was scanned. Once a users arrived on their page, we let node.js know that a player has connected, so that we can set up the game accordingly.

QR Code

Access the iPhone gyroscope and accelerometer with Javascript

When a user visits player1.php or player2.php, we have an idea of who has entered the game and we can start detecting movement of their iPhone (or any other phone that supports the device motion event). Using the built-in gyroscope or accelerometer is pretty easy in safari mobile. Keep in mind that support is limited.

window.ondevicemotion = function(event) 
{ 
  accelerationX = event.accelerationIncludingGravity.x;
  accelerationY = event.accelerationIncludingGravity.y;
  accelerationZ = event.accelerationIncludingGravity.z; 
} 

Source and demo by Alberto!

Use node.js + socket.io to communicate player movement

The more difficult part is synchronising movement from the players with the game itself. We could send an AJAX call to the server to save the current direction a user is holding its Phone in. That way, the game.php page (which shows the game on the projector) can poll the whole time to see wether or not the direction of the player has changed.

Sounds like a bad plan? It is. It's like a baby asking its mother for candy every second or two. She has no candy, because she didn't go to the store yet, so why would you bother her every two seconds with the same question. It's better to have your mom bring you some candy once she's been to the store, right? That's exactly what node.js does.

Node.js

Together with socket.io, node.js is capable of sending events around when they occur and only then. I use socket.io with node.js to do the following:

  1. Inform the game that player 1 or 2 has connected
  2. Inform the game when a user changes direction on their phone

Let node.js listen for an event

On the client we will trigger an event called "player1 start":

socket.emit('player1 start', { name: 'Joris', ready: true }); 

On the server we will listen for that same event and let the game know somebody has connected:

 socket.on('player1 start' , function (data) { socket.join("player1"); socket.broadcast.to("game").emit('player1Connected', data); }); 

As you can see, once we visit the page called player1.php, the client will send a notification to the node server and send its name and status as well. The server listens for this event and puts the user in a separate "room" called "player1". That way, we can send messages to only player1 if we would want to. The server then lets the game know that somebody has connected. Once we have both players, the game can begin.

All events are written in plain Javascript or jQuery. The only thing I've used node.js and socket.io for is triggering events at the right time. Starting the game for example is done by triggering a plain old Javascript function where you can hook up any functionality you want, like animating the ball on the canvas and displaying the score.

What I'd like to do

I think that many companies could benefit from some sort of interactive game being projected on a building, in a movie theatre or anywhere else they'd like it to show up. If you are a company that's interested in having a prototype developed, get in touch.

Worst case scenario is that we'll be playing with some prototypes on Thursday nights at the GoodBytes office :). Watch out for spontaneous projections on a building near you in Mechelen, guerrilla-style ;).

Thanks and Credits

The following resources have been a great help for getting this little game up and running. Michael Flarup for the icons template Font Awesome for the web font icons Alberto for the accelerator code snippet Webdigi.com for the great tutorial on how to build space invaders with node.js A special thanks to the Interactive Multimedia Students that stress-tested the game during their lunch break :).

Game test during lunch

When I find the time I'll try to write up a more complete tutorial about this, but for the time being, this should be enough to get an idea of what node.js, socket.io and canvas can do for you. I hope you'll find the article helpful and please share your feedback or suggestions below.

No comments? But that’s like a Gin & Tonic without the ice?

I’ve removed the comments but you can shoot me a message on LinkedIn to keep the conversation going.