This is part 1 of a 3 part series. If you get lost at any time during this tutorial, you can always refer to the solution code here.
I recently set out on the (long, confusing, and questionably documented) journey of creating a live-multiplayer game using Phaser 3 and Socket.io. Initially, I built a single-player game (check it out here https://cyberpunk-game.herokuapp.com/) and naively thought to myself “I’ll simply get the single player set up and apply multiplayer afterwords, no problem.” Wrong, Hannah. This was a problem.
The reason that building a single player framework and then applying a multiplayer aspect to it later on is a problem – is because it requires lots of refactoring to your code, file structure, and unnecessary duplicate work. When initially set up as a live-multiplayer, you will be faced with engineering problems that are most easily solved before you have massive amounts of entities, scenes and logic to go with it.
Why is multiplayer complicated? Checkout this video for a conceptual overview of how it works.
The problems that I’ve encountered in my research have made it a difficult stride to setup my game as a live-multiplayer. One reason being, that there are virtually no tutorials specific to Phaser 3 (and I mean PHASER 3, not Phaser 2) and Socket.io, that run when you smash that npm run start-dev command, or that don’t require a lot of other add on technologies that also don’t work or are confusing to learn – when you’re just trying to get the basics down.
If you are here, you’ve likely encountered these same problems in your research. Perhaps you’ve stumbled upon this tutorial, which provides a simple overview on how to setup a basic live-multiplayer game with Phaser 3 and Socket.io without additional technologies. Although, if you’ve gone through this tutorial, you’re likely banging your head on your keyboard and yelling while comparing your code to the solution code, as its riddled with bugs. I too have a keyboard imprinted on my forehead, as it took my team of four programmers to unriddle this. If you still feel compelled to complete this tutorial, worry not, I have provided the debugged solution code here.
But how about a much cooler tutorial that doesn’t have a bug infestation? If you are seeking a comprehensive, step by step, live multiplayer tutorial using Phaser 3 and Socket.io from scratch, this is the tutorial for you my friend.
Initialize the Repo:
Go to your terminal and follow your directories to wherever you want your project to belong. In your command line run: “mkdir amongus-tutorial” to create your folder. “cd amongus-tutorial” to enter the folder. Inside your folder, run the commands “git init” to initialize git and “npm init” to initialize your package.json. Go through the prompts after running npm init, you don’t have to put anything in the prompts, just press enter to go all the way through, or you can name your project and add descriptions, your choice.
Setup the package.json:
Inside of your terminal, create the following folders inside your project:
Open your project directory in the code editor of your choice, I prefer VSCode. Navigate to your package.json in your code editor. For the sake of saving time, copy the following into your package.json, it can be found in the solution code here. In your terminal (inside your project directory) run npm install. What the heck are we installing here and which ones actually matter? Heres a run through:
- Scripts: For this tutorial, we will be using the npm run start-dev script to build and start our server.
- Dependencies: We are installing express as our server, Morgan logs middleware (so you can see bugs in your terminal), and Socket.io is how we keep track of who is connected to our server and what they do. The dependencies that we wont worry about in this tutorial are axios, sequelize (they speak to your database), passport (its used for login functionality) and redux (manages state on the frontend). All of these softwares can help you down the road if you want to expand on this project. For the sake of simplicity, we will be hardcoding our database.
- Dev dependencies: we are installing babel to help us build webpack, and nodemon for node.js dev.
Setup the Server:
In your server directory, create the file index.js We need to require in the following at the top of this index.js:
Now we are going to make a function that creates our app. When it runs, it tells our app to use Morgan to log our middleware, we include a body parsing middleware that sits conveniently on express, and compression middle wear. We tell the server where to get our static files, and we provide an error handler at the end incase a client requested page associated with our app does not exist.
Below this function, we must tell our server where our home base is. But where is our home base? We haven’t created one yet, let’s make it quick. Navigate to your public folder and create a file called index.html. Include the following code:
Back in our server/index.js lets add some code to tell our server to get our index.html. We also include our second error handler, which catches errors on the server side.
Our last step for setting up our server is to listen to our Port, and boot the app. Add the following code to the bottom of your index.js file
Lastly, we need to add an index.js file to our src folder, we don’t need to add anything to it yet. And we need to create our webpack.config.js file to tell our app how to bundle.
Now smash that npm run start-dev command and take a look at http://localhost:8080/ !!!
Empty black screen? No console errors? Excellent! Our server is running.
Let’s add some Phaser magic.
Inside of our src folder (if you haven’t figured it out yet, our src folder is our client side !!) create a folder called config and add a file to it called config.js. Inside of config.js we will be initializing our Phaser game settings with the following code:
Navigate to src/index.js this is where our game instance will live. At the top of your file, import in typings:
Follow this link to the solution code’s typings file, and include it in your typings folder so that the import we just wrote can access it.
In src/index.js let’s create our game class and access the config through our super.
Our server is up, we have our game initialized, now we need to incorporate socket. Inside of your server folder, create a new folder called socket, and create a file inside of it called index.js. Now that we’ve created where our sockets will live, we can require it into our server. Go to your server/index.js and find the startListening function that we wrote. Include our socket io variable and require our socket folder in at the bottom of startListening func.
We’ve taken care of sockets on our server side, but how do they communicate with the client side? Navigate to our index.html and include the socket script above our bundle.js script:
If you run npm run start-dev, why don’t we see the console.log from our socket/index.js file that says we are connected? It’s because, although we’ve plugged socket into the right places, we haven’t initialized a socket on our game yet. Lets create some scenes and find a place for it!
This concludes part 1 of our tutorial. Click here to move onto part 2, where we will create graphics, fill out our scenes, and add logic to our sockets.