A new beginning
It has been over 3 years without a post. I want to break this silence with this post, a post about how to run a Phaser game inside a NodeJS environment. This is the first post from a new series that will explain how to create a cross-platform real-time multiplayer game.Cross-platform real-time multiplayer games in JavaScript
- Running a Phaser game inside a NodeJS environment - Part 1.
- Running a Phaser game inside a NodeJS environment - Part 2.
- Basic Socket.IO connections between client & server.
- Client-Server game state syncing.
- Interpolated syncing, or how to make things seem smooth.
- ... more to be added
Phaser game inside a NodeJS environment
How and why can you do it
Running a game (at 60fps) inside a Node.js instance is not that hard. You just need a gameLoop function that is executed 60times a second and you can do that by using a setTimeout for example. Doing this will not block the event loop between frames but while a new frame is being computed (eg. the gameLoop function is being executed) the event loop is actually blocked but the time between frames is more than enough for Node to do its stuff.
Phaser, being written in JavaScript, can be run directly in Node.js, but there are some things you have to handle:
- Phaser requires a HTML DOM.
- There is a jsdom package which creates a virtual DOM. The thing is, it's more than we need and is harder to install because of the contextify dependency. Due to the popularity of Node.js there is actually a package already created the does what we need without that contextify dependency jsdom-no-contextify.
- Phaser requires a functional Canvas element.
- I have created a mock canvas module which only adds the empty canvas functions that Phaser calls. This means that we don't have a real canvas, function calls will do nothing, but we need their declarations added so errors are not triggered.
- An alternative was to install a real canvas (the node canvas package) but it is really difficult to install (actually 2/3 times I didn't even manage to install it). The advantage with having a mock canvas is that, by doing nothing on function calls, the resources used on the server would be fewer.
- Phaser uses XMLHttpRequest to load assets.
- You need to actually load the sprite images so that their width and height can be retrieven.
- There is also a catch here: the XMLHttpRequest package works only via HTTP, but when you load resources in pixi you actually load it via an absolute file path (like file:///C:/img/asset.png) which won't work. Luckily there is a local-xmlhttprequest node package which handles this case.
- Once you load an image you also need a way to get its dimensions (width/height). For this I used the package image-size.
Now, another thing that you will learn in this series is how to use the same code both on the client and the server. This will considerably cut the development time of a multiplayer game, as you only have to write the game engine once and only add some simple conditions to check if the environment is a client or a server. To be able to do this you have to:
- Use RequireJS on both client & server. This means that you won't include all the files on the client by using <script> tags, because those are DOM specific which you include in your HTML file, but on Node you will have no HTML file. By using RequireJS you have a way to include JavaScript files on the client in the same way you do on the server.<script> tags, but by requiring them where they are needed.
- I decided to use two different Phaser library files, one for client (the default one) and one for the server (where all the phaser dependencies described above are included). I will be using Phaser v2.2.2 because the new versions didn't seem to work with RequireJS (I will update this post when I will manage to include a newer phaser version). So, the server-side Phaser library is actually a custom build (I found no way to integrate image-size package into the Phaser loader without writing code directly in the load function).
Getting started
To get started, you have to:
- Install WAMP (or another web server suitable for your platform). We'll use Apache to serve static files (like our game index.html) so we use Node.js only for the multiplayer part.
- Install Node.js. This will automatically install npm which you'll use to easily install packages (node modules).
Now you should test that everything is installed correctly. First, create a folder in WAMP's www directory add an index.html file containing a basic HTML file or a Hello World message. When you navigate to http://localhost/yourDirectory you should see that message. This means that WAMP is working.
Now, let's test Node. All node applications must have a package.json file which describes the application (name, author, etc...), most importantly it's dependencies. To create a new app open the console at your folder's location (windows, in your folder: SHIFT+RIGHTCLICK->Open command window) and type npm init. Complete the name of the app and the rest of inputs (you can keep pressing enter to skip them all).
Let's see how node works by creating a simple Socket.io server.
Create a js subfolder and an server.js file in it. In this file we will create the Socket.io server and listen to a port.
Server.js file:
Create a js subfolder and an server.js file in it. In this file we will create the Socket.io server and listen to a port.
Server.js file:
var app = require('express')(); var server = require('http').createServer(app); var io = require('socket.io')(server); var port = 3000; server.listen(port); console.log('Started Socket.io, linstening on port:' + port);
Now, if you write in console node js/server.js to run the server you will get several errors. This is because we did not include the dependencies. For this we have to run the following npm commands:
Executing node js/server.js should now result in this message:
In the next part I will explain, step by step, how to successfully run Phaser inside node and I will also post an archive containing a basic Phaser + Node app template.
If you have any suggestions for this post, or encounter problems following the steps described above, feel free to leave a comment.
npm install express --save npm install socket.io --saveThe --save part is included so that the dependencies are saved inside the package.json file. This way when you try to install your app from a package.json config you only have to type npm install and all the dependencies mentioned in the JSON file will be included.
Executing node js/server.js should now result in this message:
End of Part 1
This is all for the first part of this tutorial. You have learned what are the problems that you might encounter while trying to run Phaser in Node.js and what are the theoretical solutions for overcoming those problems. You have installed WAMP and Node.js and learned how to create a basic Socket.io server.In the next part I will explain, step by step, how to successfully run Phaser inside node and I will also post an archive containing a basic Phaser + Node app template.
If you have any suggestions for this post, or encounter problems following the steps described above, feel free to leave a comment.
Author: Cristian Buleandră
Posted on: 03 June 2015
Last updated: 03 June 2015
Excelente tutorial, thank you very much,
ReplyDeletei am looking forward to the next article
Part 2?
ReplyDeleteI might add it soon, had to work on other project and this post didn't get as much attention as I wanted. I will try continuing this tutorial this summer.
DeleteIm sad that there isn't a following
ReplyDeleteThe post didn't get much attention and the multiplayer as was working on was postponed. I may continue this post if the latest updates of Phaser/Node.js don't include a better way of running Phaser on the server.
DeletePleeeeeeeeeeeeeease!!! I need that part 2.
ReplyDeleteUnfortunately I will not continue this series. Phaser 3 will be released soon so this tutorial will become outdated anyway.
DeletePhaser 3 is out and your tutorial still worked perfectly!!
ReplyDelete