How to make a multiplayer online game with Phaser, Socket.io and Node.js

In this tutorial, we will see how to program the client and server of a very basic real-time multiplayer online game, and how to make them interact using Socket.io. In this small game, each player will move his or her character by clicking on the map, while the characters of the other players move in real-time on the screen. Although this basic game won’t be very fun, it will constitute a basis upon which you will be able to build your own exciting game.

A demonstration of this game is available here. To test the real-time multiplayer aspect, visit that page with two different windows and see what happens in one when you move in the other.

Setting

Most multiplayer online games (especially the massively multiplayer ones) follow a server-client architecture. Each player runs a piece of software called the client, responsible for displaying the game and handling the player’s input, and each client exchanges data with a central, authoritative server, that validates the actions of the players and broadcasts them to the other clients.

In our case, the client is written in Javascript with Phaser and runs in the browser of the players. This tutorial assumes basic familiarity with Phaser (game states and their associated functions, handling input, …).
The server is written in Javascript as well, using Node.js and the Express module. The client and the server communicate by using Socket.io.

The full source code for this tutorial can be found on the GitHub repository, together with instructions as how to run it on your own computer. Throughout the tutorial, the white github boxes will indicate which files contain the code I’m discussing.

The assets used for this demo are on the GitHub repository. The map is a small fraction of the map of Mozilla’s BrowserQuest. The tileset and the player sprite have been borrowed from BrowserQuest as well.

Setting up the client and the server

In this first part, we will program a basic Node.js server to serve the files to the client. We will also set the basic game files up. This part can be skipped if you are familiar with Node.js/Express and Phaser, although it might be useful to have a look at the code to get a feeling of how it is organized. I will briefly explain what this part of the code does, without entering in too many details as the focus of this tutorial is the game logic. If this is unclear, try to have a look at the relevant documentation or feel free to ask for clarifications in the comments section, I’ll be happy to clarify.

The server

server.js

We start by requiring all the Node.js modules that we will need. Note that they need to be installed in whatever environment you use (along with Node.js itself of course); you can do so using npm (e.g. `npm install express`). If you run the code from GitHub, running `npm install` will read the package.json file and install all necessary modules.

var express = require('express');
var app = express();
var server = require('http').Server(app);
var io = require('socket.io').listen(server);

Express is the module that we will use to serve files to the clients. We create a new instance called app, and by combining it to the http module, we ensure that our express app will act as an http server. Finally, we require the socket.io module and make it listen to the connections to that server. This is more or less boilerplate code to get started with simple apps.

The next step is to deliver the files depending on the path requested.

app.use('/css',express.static(__dirname + '/css'));
app.use('/js',express.static(__dirname + '/js'));
app.use('/assets',express.static(__dirname + '/assets'));

app.get('/',function(req,res){
    res.sendFile(__dirname+'/index.html');
});

These lines are necessary to be able to serve static files such as CSS style sheets or game assets that won’t be accessible directly but need to be accessed by your game. For convenience, the second argument of app.use() lets you specify virtual paths, that are not the real paths to your resources, but that will be the paths used by your scripts to access them.

We finish setting the server up by indicating which port the server should listen to and by specifying what file to serve as the root page.

app.get('/',function(req,res){
    res.sendFile(__dirname+'/index.html'); 
});

server.listen(8081,function(){ // Listens to port 8081
    console.log('Listening on '+server.address().port);
});

The client

index.html

Index.html is the gateway page that will be displayed when connecting to your server, and also in this case the page on which the game will be displayed. It is up to you to structure it however you please, but it should at least contain a div element with id ‘game‘. It should also include the Javascript files needed for your game, including socket.io. Here is how to include it:

<script src="/socket.io/socket.io.js"></script>

This works because the virtual path /socket.io/socket.io.js is automatically created when installing socket.io.

At this point, if you run the server (by typing `node server.js` in a terminal) and navigate to your app (e.g. at http://localhost:8081/ if you are running it locally and kept the default port), you should see your index.html served to you, with whatever content you have put in it a this point (maybe a “Hello World”, to make sure it works). Let’s now include game.js to set up the game. I’ll refer to this process henceforth as “running the game”.

js/game.js

We can now proceed by setting up the game canvas (assuming we have a div block with id ‘game‘) and declaring a single game state, called ‘Game‘, corresponding to a Javascript object of the same name.

var game = new Phaser.Game(16*32, 600, Phaser.AUTO, document.getElementById('game'));
game.state.add('Game',Game);
game.state.start('Game');
var Game = {};

In Game.init(), there is only one parameter to set:

Game.init = function(){
    game.stage.disableVisibilityChange = true;
};

This is not mandatory, but useful, as it will make the game keep reacting to messages from the server even when the game window doesn’t have focus (which is a desired behavior for most games).

In Game.preload(), we load the assets that we will need, including the tilemap in JSON format (exported from Tiled). I will not go into much details here about creating and dealing with Tiled tilemaps, but if you’d like me to make a tutorial to cover these aspects, don’t hesitate to let me know.

Game.preload = function() {
    game.load.tilemap('map', 'assets/map/example_map.json', null, Phaser.Tilemap.TILED_JSON);
    game.load.spritesheet('tileset', 'assets/map/tilesheet.png',32,32);
    game.load.image('sprite','assets/sprites/sprite.png'); // this will be the sprite of the players
};

In Game.create(), we start by creating and displaying our map.

Game.create = function(){
    var map = game.add.tilemap('map');
    map.addTilesetImage('tilesheet', 'tileset'); // tilesheet is the key of the tileset in map's JSON file
    var layer;
    for(var i = 0; i < map.layers.length; i++) {
        layer = map.createLayer(i);
    }
    layer.inputEnabled = true; // Allows clicking on the map
};

Notice that although clicks are enabled on the map, there is no code at the moment to deal with it; this will come once the server is up and running and the communication between client and server is working.

At this point, when running the game, you should see the map displayed, without anything else happening:

js/client.js

In index.html, include a new Javascript file, client.js, which will contain a Client object that will act as the interface between the server and the game itself.

var Client = {};
Client.socket = io.connect();

The important bit here is the second line, where we initiate a connection to the server (localhost if you don't specify otherwise between the parentheses). Each time a player navigates to your app, a connection will be established with the server. This will create a socket. Sockets are endpoints in the communication flow between the server and the client. With socket.io, we can send and receive messages through the socket, which constitutes the basic way that the client and the server will interact. Here, the socket of the client is stored in Client.socket for future use.

Real-time interactions

Now the interesting part begins. We need to make the server aware of what the players do, as well as make the clients react to messages coming from the server. When a player performs an action (connecting, disconnecting or moving), we will use the Socket.io API to send a message to the server to notify it of this action. In return, the server will use the same API to send messages to the clients when they need to be informed of the action of another player. The rest of this tutorial illustrates how to send and receive such messages and how to integrate it with a Phaser game.

Displaying the connected players

When a new player connects, a new sprite should appear in the game for all connected players, including the newly connected one. The coordinates of the sprites are determined at random by the server.

js/game.js

First, let's modify Game.create() in game.js so that the client will notify the server that a new player should be created. To that end, we add Client.askNewPlayer(); at the end of Game.create(). At the beginning, we also add Game.playerMap = {}; : this empty object will be useful later on to keep track of players.

Game.create = function(){
    Game.playerMap = {};
    var map = game.add.tilemap('map');
    map.addTilesetImage('tilesheet', 'tileset'); // tilesheet is the key of the tileset in map's JSON file
    var layer;
    for(var i = 0; i < map.layers.length; i++) {
        layer = map.createLayer(i);
    }
    layer.inputEnabled = true; // Allows clicking on the map
    Client.askNewPlayer();
};

js/client.js

Now in client.js, we need to define the method Client.askNewPlayer():

Client.askNewPlayer = function(){
    Client.socket.emit('newplayer');
};

This method will use our socket object, and send through it a message to the server. This message will have the label 'newplayer', which is self-explanatory. A second argument could be added to pass additional data, but it won't be needed in this case.

server.js

In server.js, we need to react to messages from the client. Add the following code:


server.lastPlayderID = 0; // Keep track of the last id assigned to a new player

io.on('connection',function(socket){
    socket.on('newplayer',function(){
        socket.player = {
            id: server.lastPlayderID++,
            x: randomInt(100,400),
            y: randomInt(100,400)
        };
        socket.emit('allplayers',getAllPlayers());
        socket.broadcast.emit('newplayer',socket.player);
    });
});

function getAllPlayers(){
    var players = [];
    Object.keys(io.sockets.connected).forEach(function(socketID){
        var player = io.sockets.connected[socketID].player;
        if(player) players.push(player);
    });
    return players;
}

function randomInt (low, high) {
    return Math.floor(Math.random() * (high - low) + low);
}

We tell Socket.io to listen to the 'connection' event, which is fired each time a client connects to the server (using io.connect()). When this happens, it should call the callback specified as the second argument. This callback receives as first argument the socket used to establish the connection, which, just like the client socket, can be used to pass messages.

Using the socket.on() method from the socket objects, it is possible to specify callbacks to handle different messages. Therefore, each time a specific client sends a specific message through his socket, a specific callback will be called in reaction. In this case, we define a callback to react to the 'newplayer' message. Let's decompose what is done there:

socket.on('newplayer',function(){
        socket.player = {
            id: server.lastPlayderID++,
            x: randomInt(100,400),
            y: randomInt(100,400)
        };
        socket.emit('allplayers',getAllPlayers());
        socket.broadcast.emit('newplayer',socket.player);
    });

First, we create a new custom object, used to represent a player, and store it in the socket object. As you can see, it's possible to add arbitrary client-specific properties to the socket object, making them convenient to access. In this object, we give the player a unique id (that will be used on the client side), and we randomly determine the position of the sprite. Then, we want to send to the new player the list of already connected players:

socket.emit('allplayers',getAllPlayers());

Socket.emit() sends a message to one specific socket. Here, we send to the newly connected client a message labeled 'allplayers', and as a second argument, the output of Client.getAllPlayers() which will be an array of the currently connected players. This allows newly connected players to get up to date with the amount and positions of the already connected players. Let's have a quick look at Client.getAllPlayers():

function getAllPlayers(){
    var players = [];
    Object.keys(io.sockets.connected).forEach(function(socketID){
        var player = io.sockets.connected[socketID].player;
        if(player) players.push(player);
    });
    return players;
}

io.sockets.connected is a Socket.io internal array of the sockets currently connected to the server. We can use it to iterate over all sockets, get the player property we have added to them (if any), and push them to a list, effectively listing the connected players. And finally:

socket.broadcast.emit('newplayer',socket.player);

The socket.emit.broadcast() sends a message to all connected sockets, except the socket who triggered the callback. It allows to broadcast events from a client to all other clients without echoing them back to the initiating client. Here, we broadcast the 'newplayer' message, and send as data the new player object.

To summarize what we've done in these last few steps:
- We listen to connections from clients and define callbacks to process the messages sent through the sockets
- When we receive the 'newplayer' message from a client, we create a small player object that we store in the socket of the client
- To the new client, we send a list of all the other players, so that he can display them
- To the other clients, we send the information about the newcomer

So far, our server reacts to one message from the clients. We now need to adapt the clients so they can process the 'allplayers' and 'newplayer' messages from the server in return, thus completing the loop `connect - notify the server I'm here - get info in return - display it`. Note that the 'newplayer' message sent by the client and the one sent by the server are not the same; I chose to give them the same label because they convey the same kind of information, but they will be treated separately since they have different endpoints (the server for the former, the client for the latter).

js/client.js

In client.js, add this code:

Client.socket.on('newplayer',function(data){
    Game.addNewPlayer(data.id,data.x,data.y);
});

Client.socket.on('allplayers',function(data){
    console.log(data);
    for(var i = 0; i < data.length; i++){
        Game.addNewPlayer(data[i].id,data[i].x,data[i].y);
    }
});

As you can see, the same syntax to handle messages can be used on the client side. When data is sent along a message, it can be retrieved as the first argument of the callback on the receiving end. Therefore, the 'data' object fed to the 'newplayer' callback corresponds to the socket.player data sent by the server. For the 'allplayers' message, it is a list of socket.player objects. In both cases, this data is processed by calling Game.addNewPlayer(), which we can now define in game.js:

js/game.js

Game.addNewPlayer = function(id,x,y){
    Game.playerMap[id] = game.add.sprite(x,y,'sprite');
};

This method creates a new sprite at the specified coordinates, and stores the corresponding Sprite object into an associative array declared in Game.create(), with the supplied id as the key. This allows to easily access the sprite corresponding to a specific player, for example when we need to move or remove it (see below).

At this point if you restart the server (so the last modifications are taken into account) and navigate to your game, you should see a small character displayed, corresponding to your sprite. If you connect with other browsers, additional characters should pop up on the screen.

Handling disconnections

As is, when a player disconnects, his sprite will remain on the screen of the other players, which is not desirable. This can be fixed by processing the 'disconnect' message that the server automatically receives when a client actively disconnects or times out. This message can be treated just like any other, just as we did for 'newplayer' for example: by binding a callback to it within the io.on() method:

server.js

io.on('connection',function(socket){

    socket.on('newplayer',function(){
        socket.player = {
            id: server.lastPlayderID++,
            x: randomInt(100,400),
            y: randomInt(100,400)
        };
        socket.emit('allplayers',getAllPlayers());
        socket.broadcast.emit('newplayer',socket.player);

        socket.on('disconnect',function(){
            io.emit('remove',socket.player.id);
        });
    });
});

In reaction to the 'disconnect' message, we use io.emit(), which sends a message to all connected clients. We send the message 'remove', and send the id of the disconnected player to remove.
Note: Thanks to Kaundur for pointing on that the 'disconnect' callback has to be registered within the 'newplayer' callback; if not, and 'disconnect' is somehow called before 'newplayer', the server will crash!

js/client.js

In client.js, this is processed as follows:

Client.socket.on('remove',function(id){
    Game.removePlayer(id);
});

And in game.js:

js/game.js

Game.removePlayer = function(id){
    Game.playerMap[id].destroy();
    delete Game.playerMap[id];
};

This illustrated the use of the Game.playerMap data structure, by the way. No need to loop over sprites; the id allows you to fetch it immediately. Now all that remains to do is process and broadcast player movements.

Handling player movements

js/game.js

It's time to complete Game.create(). We basically want that when the map is clicked, the coordinates are sent to the server, so that the position of the player who clicked can be updated for everyone. Add the following line to Game.create():

layer.events.onInputUp.add(Game.getCoordinates, this);

Now, the map will react to clicks by calling the Game.getCoordinates() method, which we can define as follows:

Game.getCoordinates = function(layer,pointer){
    Client.sendClick(pointer.worldX,pointer.worldY);
};

Callback of onInputUp events in Phaser receive as second argument the corresponding pointer object, which contains two properties worldX and worldY that we can use to know where, on the game map, did the click take place. We can then pass these coordinates to Client.sendClick() in client.js:

js/client.js

Client.sendClick = function(x,y){
  Client.socket.emit('click',{x:x,y:y});
};

Which simply sends the coordinates to the server, with the label 'click'. No need to send any player id, since the socket is client-specific and associated to only one player.

server.js

In server.js, here is the final list of message callbacks:

io.on('connection',function(socket){

    socket.on('newplayer',function(){
        socket.player = {
            id: server.lastPlayderID++,
            x: randomInt(100,400),
            y: randomInt(100,400)
        };
        socket.emit('allplayers',getAllPlayers());
        socket.broadcast.emit('newplayer',socket.player);

        socket.on('click',function(data){
            console.log('click to '+data.x+', '+data.y);
            socket.player.x = data.x;
            socket.player.y = data.y;
            io.emit('move',socket.player);
        });

        socket.on('disconnect',function(){
            io.emit('remove',socket.player.id);
        });
    });
});

The x and y fields of the player property of the socket are updated with the new coordinates, and then immediately broadcast to everyone so they can see the change. Now the full socket.player object is sent, because the other clients need to know the id of the player who is moving, in order to move the proper sprite on-screen (even though, in this minimalist game, there is no actual way to distinguish the players).

js/client.js

Back to client.js, we need to handle the 'move' message from the server, so that the clients can react to another player moving:

Client.socket.on('move',function(data){
    Game.movePlayer(data.id,data.x,data.y);
});

The process should start to become familiar to you. In game.js:

js/game.js

Game.movePlayer = function(id,x,y){
    var player = Game.playerMap[id];
    var distance = Phaser.Math.distance(player.x,player.y,x,y);
    var duration = distance*10;
    var tween = game.add.tween(player);
    tween.to({x:x,y:y}, duration);
    tween.start();
};

We again make use of the Game.playerMap structure to retrieve the proper sprite, and then we tween it to make the movement progressive.

Conclusion

And that's it! If you now run the game, you should be able to see the sprites move and (dis)appear according to the actions of other clients in real-time. Many improvements are possible from there, which I leave to you as exercises. To name a few:
- Animate the movements of the sprites, using a spritesheet
- Specifying "collisions", that is, areas where the players cannot move
- Use your own, bigger map and make the camera follow the player
- Allowing the players to specify a name for their character, or to change their sprite

If there is demand for it, I would be very inclined to make tutorials for these possible improvements, or others; feel free to contact me if you are interested.

For a more complex example of a multiplayer online game made with Phaser, have a look at Phaser Quest!

Related workd

For a more modern syntax, check out TVscoundrel's refactoring of the source code in ES2015!

Jerome Renaux

I’m an independent game developer, working mainly on browser-based multiplayer online game (HTML5 & Javascript).
I love to discuss about all aspects of game development so don’t hesitate to get in touch!

More Posts

Follow Me:
Twitter

Jerome Renaux

I’m an independent game developer, working mainly on browser-based multiplayer online game (HTML5 & Javascript).
I love to discuss about all aspects of game development so don’t hesitate to get in touch!

  • ‘Isaac David S L

    nice article, i liked it !

  • Darkmatter Jesus

    Thank you so much for doing this!!!

    • Jérôme Rx

      You’re welcome, glad this helps! Don’t hesitate to ask if anything is unclear!

  • Sébastien Simon

    Thx so much. Very useful !

  • Richard Hoddinott

    I’ve been looking for a good tutorial on Phaser + socket.io, and this looks like exactly what I’ve been waiting for – thank you for writing this. I’ll be working through it over the next couple of days so I might be in touch if I get stuck!

  • Mii Sussbauer Sußbauer

    thanks a ton!

  • Great job! I love Phaser!
    I will be very happy to see the “Tower Defence” game in your realization.

    • Jérôme Rx

      Thanks! But what do you mean by the Tower Defence in my realization?

  • sergio

    hola, tengo unapregunta, creare un juego con phaser.js y quisiera guardar los datos de los personajes en una base de datos pero no tengo muy bien claro como hacer la conexion a la base de datos, quisiera saber si con nodeJS podria, gracias

    • Jérôme Rx

      Esta posible con MongoDB. El source code de Phaser Quest contiene ejemplos de este, por ejemplo in GameServer.savePlayer() y
      GameServer.loadPlayer() (pero deberías leer un tutorial sobre MongoDB & Node.js). In el futuro voy a probar escribit un tutorial sobre esto!

  • Mehul Ahuja

    How will you handle collisions between the clients?

    • Jérôme Rx

      Essentially, what you would need to do is keep track on the server of
      the positions of the players while they move, and to check at a regular
      interval (e.g. every 50ms) if they overlap. When they do, you can
      interrupt the movement.
      For an example, you can check how I do for Ensemble: http://www.dynetisgames.com/2017/04/20/project-ensemble/ . In that game you can move with either the keyboard or the mouse, and the mouse movements are similar as in this tutorial, except that there is collision detection with the blocks.
      In the future I’ll post additional tutorials like this one, including one specially about collision detection. 😉

      • Mehul Ahuja

        Thanks for replying! This is exactly what I was trying to do but the I didn’t get what I expected. To explain suppose I have 2 players X and Y (both are physics bodies) and I’ll be talking with respect to X.

        In first case, so when Y spawns, at X’s side it is instantiated as a non physics body to reduce the overhead because I only need to keep track of the x and y coordinates. In this case I just need to check the bounds and react accordingly right?

        In second case in which I have been failing miserably since yesterday is when I instantiate Y as a physics body for X. Now this became really hard to control, the game was behaving erroneously. As soon as an “move player” event was called, Y gains a velocity and goes outside the map. So I tried to set velocity to “0” for Y at X in the update method. This lead to Y’s movement become shaky.

        What do you think about the second case? How should I handle it? Or should I just go for the first case?

        Thanks a lot again 🙂

        • Jérôme Rx

          If you use physics, it can be a bit more tricky to synchronize. The most common solution is to run a physics simulation on each client and let it handle collisions etc. In this case you can use Phaser built-in physics engine. In addition, to prevent cheating, you need to check for collisions on the server as well, as I explained above. In my experience this doesn’t require frame-by-frame physics as on the clients, it can be a bit coarser. Whenever the server detects an issue, it can signal the clients and adjust them immediately back.

          So if you run physics on both clients, and the physics are deterministic, given the same inputs they should behave the same, but you should also make it possible for the server to authoritatively change the coordinates of the sprites on the clients.

  • sergio

    holaa crack!, quisiera una ayuda, realizare un juego sencillo en phaser de puntuaciones de scores, quisiera generar un inicio de secion y guardar la informacion de cada usuario y la puntuacion de cada usuario, es un juego online para mobil, quiero utilizar phaser con node js socket y mongo db, podrias ayudarme, o si sabes de algun tutorial para el proyecto… graciass

  • sergio

    una pregunta estoy desarrollando un juego con el framework phaser de js, en el lado del cliente genero una variable para guardar mis estadísticas llamada puntos, esa variable quisiera enviarla al servidor (node.js) y luego guardarla en una base de datos (mongo db), podrías ayudarme,? con socket.io se puede??

    • Jérôme Rx

      Si se puede con socket.io, por ejemplo “io.emit(‘points’,puntos)”, y en el lado del server “socket.on(‘points’,function(puntos){/*Hace algo*/})

      Para este typo de preguntas, es mejor mandarme un email. 😉

      • sergio

        Holaaa, entonces.por.acá puedo.preguntarte?, es que la verdad.se.Muy poco. Del.tema,.podrías ayudarme en el.lado del.cliente.como y en el lado.Del.sserver como?? Sólo creo una variable puntos.en phaser,.que se.incrementara con las.coolisiones y después que hago? Para enviarla al servidor y después a la.base de datos

        El 13/06/2017 7:40 a. m., “Disqus” escribió:

  • Kresimir Majic

    Thank you so much! This is great!

    I’d like to have the sprite follow the cursor. How do I force the server to request the cursor coordinates from clients, and how often should I do (per second) it to make it smooth?

    • Jérôme Rx

      It’s not the server who should request it, but the client who should send it on its own. You can set a loop on the client side with setInterval(), and in it, use the emit() method of Socket.io to send the mouse coordinates each time (something like socket.emit(‘coordinates’,{x:pointer.worldX,y:pointer.worldY});).
      The rate at which this should take place depends on the game you want to make, but I guess 5 or 10 times per second should be a good start (don’t hesitate to experiment with different rates and see what suits you best).

      • Kresimir Majic

        Thank so much! I got it working, and then hit a bigger problem – server side physics. Since the clients will be using Phaser, I’d like to use similar syntax on the server for collisions/physics. Is this possible?

        • Jérôme Rx

          Yes it is possible. I suppose you mostly want to check for collisions. If your obstacles are static, then the client-side physics will always correctly compute collisions. You only need to do it on the server side as well to avoid cheating, but for that you can afford less precise physics than on the client, to save resources.
          If your obstacles are dynamic (moving, changing shape, appearing/disappearing), then it’s more complicated, you need accurate physics on the server-side that work the same way as on the clients-side to avoid discrepancies. So in that case, yes, you should reproduce your clients physics, which in this case corresponds to reproducing what Phaser does in that respect, but on the server.

          You can look at the Phaser code to get a feeling of how they do, and re-implement the parts you need for the server. The idea is to only reproduce what you need, you don’t want to reproduce and run all the physics-related aspects of Phaser, that would be way too much.
          Another solution is to *not* use Phaser physics on the client, if you think it’s too complicated to reproduce. That’s what I did for Ensemble (see the code in the article about it). I wrote some basic collision detection code myself (a single method actually), which is *shared code* between the clients and the server, and that’s what I use all the time. The fact that it is shared code guarantees that it’ll work in exactly the same way, without discrepancies and headaches. (I still use Phaser for the client, but simply not its physics. You can decide which parts to use and which to make yourself.)

  • Massimo Saliba

    Great tutorial! Helped me get up to speed with networking.

    I just want to point out that one should move the Client.socket.on(‘move’…) into and at the end of Client.socket.on(‘allplayers’…). Currently, if another player clicks to move while the players are still being loaded, the game script will throw an error because it tries to move a player which does not yet exist in the local Game.playerMap.

    With this change, players can only move once they are all loaded into the array.

    • Jérôme Rx

      Good point! I have updated the source code accordingly, thanks.

      • Massimo Saliba

        Now that I think about it, even the Client ‘remove’ callback might suffer from the same problem. Might have to move that in as well.

  • Kántor Endre

    Hi,
    Thanks for the article!
    I have already made a html5 multiplayer game ( http://teamball.io ), but haven’t used any game engine. For my next game I want to try to use Phaser.
    Is it possible to use Phaser engine on server side? It would be nice if the same code can run on client and server. Off course rendering disabled on server, and maybe physics disabled on client side, or just used for interpolation.
    Have you tried this?

    • Jérôme Rx

      Hi Kantor,
      Very cool game! Really entertaining.
      Last time I checked, there was no straightforward way to run Phaser on the server. I think this has evolved a bit recently ; try to search for the “Phaser headless” keywords. That being said, I think the overhead would still be quite big. My personal preference is to keep the server-side code as lean as possible, and to use Phaser only on the client side. Normally, the only Phaser functionalities that would be needed on both sides are the physics computations, i.e. movement and collisions. For one project, I found that implementing this code myself (and taking a lot of inspiration from the actual Phaser code), and having it shared by the client and server, was the cleanest way to go. But of course it was for simple movement and collision detection, nothing very fancy. If you need something a bit more advanced, you might feel that having to re-implement the physics yourself defeats the purpose of using a game engine. I guess it’s a trade-off.
      If you use P2 physics, since it’s a standalone library, it might be more straightforward to run it on its own on the server, but it tends to be quite computationally intensive and maybe overkill for your needs.
      If you find an approach that works well for you, don’t hesitate to let me know, it’s always good to know. 😉

      • Kántor Endre

        Hello,
        Thanks for the answer.
        In teambal.io, we used P2 on server, althought I had to modify it a little bit, because of performace issues (I reimplemented the broadphase, because normally it checks every possible combinations between bodies, but in my game, I exactly know which bodies could collide with which others.)
        In my next game, I want to keep using P2 becuase it worked well.
        So what do you think, should I try to use p2 on server, with phaser on client?

        • Jérôme Rx

          Yes I’d go that way, especially if you already have experience with P2 on the server. But in addition I would use physics on the client as well to make the client more responsive (client-side prediction).

      • Shreds

        I’m trying to decide which technologies to focus next and the 3 options I’m looking at are Node, Python (asyncio) and Elixir. I fell in love with Elixir but it may not be the right choice for certain things and I’m not sure if it’s the best options for web games. Could you guys share your opinion on this topic?

        When it comes to the server authoritative issue (prevent cheating etc) is node.js an advantage over elixir and python because of the possibility of using the same js library on the server and client?

        Maybe it’s still interesting to use elixir and use node.js just for the parts of JS code that is used both on the server and client. However, as far as I know elixir/erlang does not have a simple low latency way to integrate with node.js at this time. I haven’t been able to find information on a node.js elixir/erlang nif integration. Could something like c/c++ box2d be an alternative since there is a port for javascript and it might be easier to integrate with elixir? I think there is more documentation on integrating c/c++ libraries with erlang/elixir. However, that would still add complexity and it may not be worth it.

        In general, how much js code is duplicated in the client and server when it comes to node.js web games? Could a physics library compiled to WebAssembly help with performance on the node side?

        The game State of Decay from Undead Labs used elixir and 10% C# on the Service Platform. I’m not sure if they did any game simulation with elixir and I suspect that the game servers are built with C#. Watch the video “Building And Releasing A Massively Multiplayer Online Game” on youtube if you are interested. Jamie talks about how they used Elixir on State of Decay Service Platform.

        • Jérôme Rx

          Dear Shreds,
          Indeed, having shared code between client and server is a plus, not only to prevent cheating but simply to prevent bugs and weird mismatches between client and server behavior. But code sharedness can also be achieved in python for example, as long as you write both client and server in the same language. (Of course if you specifically want to make a browser game, then your options are indeed more limited and code sharedness more or less requires javascript.)
          In my experience, only the core parts of the logic of the game need to be represented on both client and server, which includes physics if you need some. Both sides also need a way to keep an up-to-date representation of the game world and its content, in any way you want. All which is not interesting to the server doesn’t need to be shared and can be implemented entirely autonomously in the clients.

  • Maciej Szuchta

    Awesome !! Great tutorial, exactly what I have beed searching for 🙂

  • Nicolas Naranjo

    I´ve been trying to change the map exporting all the files needed (tmx, json and png)but I’ve the encountered the same problem all day long.

    phaser.min.js:26 Uncaught TypeError: Cannot read property ‘2’ of undefined
    at Object.parseTiledJSON (phaser.min.js:26)
    at Object.parse (phaser.min.js:26)
    at new c.Tilemap (phaser.min.js:25)
    at c.GameObjectFactory.tilemap (phaser.min.js:15)
    at Object.Game.create (game.js:22)
    at c.StateManager.loadComplete (phaser.min.js:10)
    at c.Loader.finishedLoading (phaser.min.js:20)
    at c.Loader.processLoadQueue (phaser.min.js:20)
    at c.Loader.asyncComplete (phaser.min.js:20)
    at c.Loader.fileComplete (phaser.min.js:20)

    Is there something I need to change inside the phaser.min.js file for the new map?

    • Jérôme Rx

      Hi Nicolas,
      Could you try using the non-minified Phaser file? That way we can see on what line something goes wrong.
      But normally it should go well, Tiled exports valid JSON files so the parsing should be ok. We’ll know more with the error line.

      • Nicolas Naranjo

        Okay thanks. I’ll post as soon as I get back in town. I’m not that familiar with Phaser. What do you mean by non-minified Phaser file? I’m currently using the one you have on your Github link

        • Jérôme Rx

          Yes I’m using the minified version, hence the extension .min.js.Minified libraries are more compact and thus load faster, but are very inconvenient to debug. Instead you can grab from the Phaser repo the non-minified version of Phaser and use it instead. This is the preferred thing to do in development. Let me know if you don’t find the right files or don’t manage to do the swap. 😉

          • Nicolas Naranjo

            It was a parsing problem with the json file but a friend of mine already solved it. Thanks for the aid. Great tutorial