In this hands on lab, we'll make a multiplayer chess game that where your moves are shown on your opponent's screen in real-time. Instantly. Checkmate.
After completing the exercises in this lab, you will be able to:
- Create a Node.js web app, run, and debug it locally
- Create a basic a Socket.io server
- Publish your server to Azure from GitHub
Estimated time to complete this lab: 60 minutes
In order to complete the lab, you need the following pre-requisites
- Windows 10, Mac OS 10 Yosemite, or Linux
- Visual Studio Code
- Node.js
In order to complete the lab, you need the following prerequisite online accounts
- Microsoft account – Needed to use Microsoft Azure
- Microsoft Azure Subscription – A free trial is sufficient
- GitHub – Required to deploy code to Azure
This lab contains the code for each of the completed steps below. Feel free to look at or use the code from the steps if you get lost or need help. If you replace your code from one of the steps, or skip a few steps, you'll need to install the Node package dependncies for that step. This step is not required if the are following along with the below steps
> npm install
We will create a basic Node.js web app that serves up some HTML content using the Express framework and run it locally.
-
Open the Node.js command prompt from the task bar or by searching for it in Start.
-
Make a new folder named chess that will contain our source code and navigate to it
> mkdir chess
> cd chess
- After you create the folder, now you need to create the package metadata for your node app. This file will include all of the project decencies.
> npm init
-
This will walk through a tutorial, keep the defaults except name your file app.js
Note: Your file needs to be named app.js or server.js to run on Azure.
-
List the folders contents and open the package file
> dir
-
Open the current folder in Visual Studio Code by typing
> code .
-
Observe your project metadata displayed in Visual Studio Code by clicking on the package.json file.
-
Click on the new file button and create a new file named app.js
-
In your app.js file paste in the following code. This is the code for your web server.
var express = require('express'); var app = express(); app.use(express.static('public')); var http = require('http').Server(app); var port = process.env.PORT || 3000; app.get('/', function(req, res) { res.sendFile(__dirname + '/public/default.html'); }); http.listen(port, function() { console.log('listening on *: ' + port); });
-
Create a new folder called public and create another file called default.html in the same folder and type hello world into it. Go ahead and save it.
-
Switch back to the Node.js command prompt and type npm install express --save. This will add the express web framework to your node app so you can host web content.
Note: The --save parameter adds a package dependency automatically for you in the package.json file.
> npm install express --save
-
Switch back to Visual Studio Code, click the Debug button on the left and hit the play button to start your project.
-
You can see in the Debug Console that the “listening on *: 3000” console message was printed out so we know our code is working. Let’s see if it’s hosting the page.
-
Open your browser and navigate to http://localhost:3000 and you’ll see your webpage
- Chessboard.js – This is a full interactive touch ready chessboard that let’s you programmatically place chess pieces, respond to player movements through event callbacks, and customize piece theme. This is the UI and visual behavior.
- Chess.js – This is the chess logic. It will know if something is a valid chess move and maintain the game logic and state. What’s cool is that it’s compatible with Chessboard.js by using a standard FEN notation for board layout and game moves.
-
Download the __LAB RESOURCES folder from this lab repo and copy it's contents into your /public/ folder.
Note: The __LAB RESOURCES folder contains the chess libraries, images for the chess game, and Jquery. Even though we don't use JQuery for our game, the Chessboard.js library depends on it.
-
Add the chess markup to your default.html in your /public/ file.
<!doctype html> <html> <head> <title>Chess</title> <link rel="stylesheet" href="lib/chessboard-0.3.0.min.css"> <link rel="stylesheet" href="/default.css" /> </head> <body> <div id='gameBoard'></div> <script src="lib/chess.min.js"></script> <script src="lib/chessboard-0.3.0.min.js"></script> <script src="lib/jquery-1.11.1.js"></script> <script src="/default.js"></script> </body> </html>
-
Create a new file named default.js in your /public/ folder and paste in the following source code.
var board; var game; window.onload = function () { initGame(); }; var initGame = function() { var cfg = { draggable: true, position: 'start', onDrop: handleMove, }; board = new ChessBoard('gameBoard', cfg); game = new Chess(); }; var handleMove = function(source, target ) { var move = game.move({from: source, to: target}); if (move === null) return 'snapback'; };
-
Create a new file named default.css in the /public folder. Copy the below styles to center the board on the page and give it a width.
body { overflow-y: auto; display: flex; align-items: center; justify-content: center; } #gameBoard { width: 400px; }
-
Finally, we need to go run the full game that we created. Click the play button to start debugging the Chess game. You’ll see that it’s running!
What’s going to make our chess game special is that it’s real-time and superfast to make, and respond to chess moves. WebSockets and the Socket.io JavaScript framework are the special sauce that is going to make this work. Respond to a simple Socket.io message
- Socket.io - A client and server Javascript framework for doing real-time stuff with WebSockets
- Open the ‘Node.js command prompt’ and type ‘npm install socket.io’ This adds the project dependencies to our project.
> npm install socket.io --save
-
Add an additional reference in your public/default.html to include the Socket.io client-side library above your other script references.
<script src="/socket.io/socket.io.js"></script>
Note: Libraries that your default.js code depend on, need to be declared before default.js if your loading them at the end of the body like this sample does.
-
Update /public/default.js to send a message to the server when someone clicks on the page.
// setup my socket client
var socket = io();
window.onclick = function(e) {
socket.emit('message', 'hello world!');
};
-
Now update /app.js to respond to that message by outputting to the log.
// setup my socket server var io = require('socket.io')(http); io.on('connection', function(socket) { console.log('new connection'); socket.on('message', function(msg) { console.log('Got message from client: ' + msg); }); });
Now when you run it, observe in the console that your message made it across when you click on the page!
In our basic Socket.io server above, we just sent a message to the client every time someone clicked the button in their browser. For the chess game, all we need to do is send the chess move data to the Socket.io server every time there’s a move and send it to the other player. We’re going to use the same socket.emit() function to send a message, and the socket.on() handlers to respond to them.
-
Update your /public/default.js client to send a move with socket.emit when they make a move on the chess board.
// called when a player makes a move on the board UI var handleMove = function(source, target) { var move = game.move({from: source, to: target}); if (move === null) return 'snapback'; else socket.emit('move', move); };
-
On the server in /app.js replace our simple onmessage handler with a handler for chess move.
io.on('connection', function(socket) { console.log('new connection'); // Called when the client calls socket.emit('move') socket.on('move', function(msg) { socket.broadcast.emit('move', msg); }); });
Now that the server is broadcasting the move to the opponent all we need to do is handle that on the client to actually display the move. We just do that with another socket.on() callback, this time on the client. I think it’s super cool that Socket.io has the same programming model whether you’re on the client or server.
-
Update your /public/default.js client to handle a move with a socket.on handler.
// called when the server calls socket.broadcast('move') socket.on('move', function (msg) { game.move(msg); board.position(game.fen()); // fen is the board layout });
-
Now run your server and try out your game. When you make a move on when browser you should see it change on the other tab.
It’s great we’ve got our game working on our local Express server but that’s not enough for me. I need to put it out there so I can start playing faster chess with my family. To do this, we need to publish it on the internets. It’s a Node app so there are a number of places I could publish it like a Heroku app or an AWS EC2 instance. I’m going to use Azure, since I like how it lets me deploy from GitHub. Fork a project from GitHub
- Microsoft Azure account - You can get a free account with a bunch of free hosting credits to spend, or if you're a Student or Startup you can get plenty of free hosting to go live.
- GitHub account - GitHub is a free source control and versioning system that's awesome and you should be using it.
-
Go to http://github.com/dwcares/realtimeweb-hol and click the fork repository button.
Note: You need to be logged in with a GitHub account to complete this step.
-
Forking the repository, makes a copy for you to play with. It essentially puts it in your sandbox to play with. We’re going to deploy your copy of the repository directly to Azure next.
-
Go to http://portal.azure.com and log in with your Microsoft Account
-
When you are at the Azure Portal, click the new button then click the Web + Mobile category and Web App button.
-
Specify the details for your website. Note: The App Service Name corresponds to the beginning part of your url.
-
Once the page is created, you need to deploy. Thankfully, Azure has a "Continuous Deployment" option. This will take the code on github and automatically deploy it when there are any changes.
-
Click settings in the header, and choose, Continuous Deployment from the list. Next, choose GitHub as the place to deploy from.
-
You will need to authorize your account by logging in with your GitHub credentials. Follow the onscreen instructions.
-
Choose the repository that we forked for this lab.
WebSockets are not enabled by default on Azure WebSites, but you can easily enable them.
-
Click the Application Settings button on your website.
-
Scroll down to the WebSockets switch and enable it.
-
Click the Save button on the top.
Go ahead and navigate to the url of your webpage in any browser! Congratulations! You've sucessfully built a real-time multiplayer chess game using Node.js, Socket.io hosted on Azure.
- We built a simple JavaScript chess game with Chess.js and Chessboard.js
- We built a simple Node.js and Express server that hosts the chess game JavaScript
- We added Socket.io to our Node server to send and handle messages from the clients, first with a simple buton
- We sent Socket.io messages to the server when the player completes her move, and broadcast it to the clients from the server.
- We published the whole game online.
- Create a menu and a lobby to find opponents
- Wrap the UI in a better framework like Ionic
- Ship on mobile platforms using Cordova
- Consider building a 3D interface in Unity
- Use REDIS Cache for variables so the server can scale beyond one instance