How to use Socket.IO and build your first multiplayer game!
Tags: javascript, todayilearned, tutorial, webdev
Published: 2020-09-28 04:12:55

# Prerequisites:
## Must-haves
* node.js
* npm
* express
* socket.io
* VS Code

# Introduction

## Backstory

If you read my other [post](https://dev.to/denislav__/the-jsourney-learn-with-projects-not-videos-1hg1) you already know what we are going to build. If not - let me explain. We are going to build a version of [ChrisOnCode's 'Crazy Buttons' lesson](https://scotch.io/courses/getting-started-with-javascript-for-web-development/crazy-buttons). We are going to create a button which when clicked, moves to a random location within the document. We are also going to make the movement real-time so other people see if there is somebody else clicking it.

## What is socket.io

As stated by the developers themselves: "*Socket.IO is a JavaScript library for realtime web applications. It enables realtime, bi-directional communication between web clients and servers. It has two parts: a client-side library that runs in the browser, and a server-side library for Node.js*"

So basically it's a library that allows us to create realtime applications. An example of such is the .io games and the Facebook chat. I suggest you take a look at their official [website](https://socket.io/docs/). Checking [this](https://dzone.com/articles/everything-you-need-to-know-about-socketio) link could also help you understand how it works.

Now you know what we are going to build as well as with what.

# Setting up the environment

As I am using Windows, I will be using Windows terms but if you're using another OS I am sure you will manage. Okay, we will start by setting up the environment. Create a new folder and name it **The internet button**. Open VS Code in the folder and create the following structure:
![Folder Structure](https://dev-to-uploads.s3.amazonaws.com/i/sdwrtsrus6oi1l3lfd3h.png)
 

Now we need to build the fundamentals of our application. Open a terminal in the directory and type
```
npm init
```
Leave the values blank, or add your name and description - it's your choice. We also need to install **nodemon** so we don't have to restart our application each time we make a change. Do so with

```
npm install -g nodemon
```

The last packages we need to install are **express** & **socket.io**

```
npm install --save express socket.io
```
After all the package installation, your package.json should look similar to this:
![package](https://dev-to-uploads.s3.amazonaws.com/i/agx0dtg11dnh1e5zt1e9.png) 

Cool, we are ready and set. Let's get to work!

# Building the app

### Adding our variables

We will start with creating a **server.js** file inside our *server folder*. Now let's setup all the variables we need. We will start loading our modules first. Add the following 4 variables:
```
const path          = require('path');
const http          = require('http');
const express       = require('express');
const socketIO      = require('socket.io');
```

Okay, now let's set-up the express server. We will first set our path to serve our HTML through the **public** folder we created:
```
const publicPath    = path.join(__dirname, '/../public');
```
We also need to specify a port our app is going to run on. Let's go with 3000: 
```
const port          = process.env.PORT || 3000;
``` 
Now we call our express function with:
```
let app             = express();
```
We then specify the http method to let HTTP connection in:
```
let server          = http.createServer(app);
```
Lastly, we set up our socketIO connection:
```
let io              = socketIO(server);
```

Our **server.js** file should have the following lines of code:

```
const path = require('path');
const http = require('http');
const express = require('express');
const socketIO = require('socket.io');

const publicPath = path.join(__dirname, '/../public');
const port = process.env.PORT || 3000;
let app = express();
let server = http.createServer(app);
let io = socketIO(server);
```

### Setup our functions

We need to set our express server to finally serve the content: 
```
app.use(express.static(public path));
```
And finally connecting to the port:
```
server.listen(port, ()=> {
    console.log(`Server is up on port ${port}.`)
});
```

Cool, we are all set. Now go inside the *public* folder, create a simple **index.html** file and add something to it. I am going to create a blank HTML document and add an h3 tag containing "Welcome to the socket.io training!". Go to your browser and type **localhost:3000** to verify everything is working.

Perfect. Let's advance!

## Setting up the front-end

As this is a *socket.io* tutorial I'm not going to fall into details on how to set-up your HTML & CSS. Instead, I'm going to give you a link to the project without the socket.io part and we will build that instead. [link](https://github.com/ascii-naut/socket-io-tutorial-post)

If you clone the project, keep in mind you have to create the folder *server* and add your **server.js** file. You also need to add **app.js** inside the *public/js* folder.

## Socket.io

### Variables

Okay, we already know what socket.io is and how it works. It is now time to make it work with our buttons. Insite **public/js** we are going to create an **app.js** file. We add our socket at the top
```
let socket = io();
```

We get our starting section. It contains components, visible before we click the "Start" button and disappear when we start the game.

```
const startingSection = document.querySelector('.starting-section');
``` 

And the 'Start' button...

```
const homeBtn = document.querySelector('.home-btn');
``` 

Finally, our 'crazy' button. The one that moves:

```
let crazyButton = document.getElementById('crazyButton');
``` 

### Socket.io server connection

Go to the **server/server.js** file and open a socket.io connection with the following code:

```
io.on('connection', (socket) => {
	console.log('A user just connected.');
    socket.on('disconnect', () => {
        console.log('A user has disconnected.');
    })
});
```

This is a built-in function. Whenever a new connection is made, the code within it will be executed. We include another built-in function **disconnect** which is self-explanatory.

We can test this by starting nodemon (**nodemon server/server.js**) and browsing to localhost:3000. Open the terminal in VS Code and check if a message is being logged.

### Start Game real-time

Let's create the functionality for the "Start" button. We are going to hide the **.starting-section** components and also make it real-time so they hide for other players as well. Navigate to **app.js** and add a click event listener to the *start button*:
```
start button.addEventListener('click', () => {
    
})
```
Inside our event listener, we must emit a message to the socket.io server with **socket.emit('startGame');**:
```
startButton.addEventListener('click', () => {
    socket.emit('startGame');
});
```
Now on the server side(**server.js**), we must create a 'listener' for that message:
```
socket.on('startGame', () => {

})
```
We emit a message back to all the connected clients:
```
socket.on('startGame', () => {
	io.emit('startGame');
})
```
We then process the 'message' from the server in our **app.js**:
```
socket.on('startGame', () => {
});
```
and we call the function *hideStartButton()*:
```
socket.on('startGame', () => {
    hideStartButton();
});
```
Finally, we declare our *hideStartButton* function:
```
function hideStartButton() {
    startButton.style.display = "none";
    crazyButton.style.display = "block";
    startingSection.style.display = "none";
}
```

Now we test if everything is working in localhost:3000:
![9b72a53939f52dd58052583a273a1851](https://dev-to-uploads.s3.amazonaws.com/i/6exkq64cvre3tzqwnu4d.gif)
 
### Move the button real-time

For this part everything is almost the same with only one difference - we must pass data from our app to the server, process it, and return it to each connected client.

We add a event listener to our crazy button & emit a message containing an object with two values - offsetLeft & offsetTop, which are a Math.random multiplied by the innerWidth & innerHeight of our window - the button's clientWidth & clientHeight:
```
crazyButton.addEventListener('click', () => {
    socket.emit('crazyIsClicked', {
        offsetLeft: Math.random() * ((window.innerWidth - crazyButton.clientWidth) - 100),
        offsetTop: Math.random() * ((window.innerHeight - crazyButton.clientHeight) - 50)
    });
})
```

The server then receives these values under the form of 'data' variable & emits them back:
```
socket.on('crazyIsClicked', (data) => {
    io.emit('crazyIsClicked', data);
});
```

Our app.js file then receives the data and input it in the function, which moves the button:
```
socket.on('crazyIsClicked', (data) => {
    goCrazy(data.offsetLeft, data.offsetTop);
});
```

We create our goCrazy function:

```
function goCrazy(offLeft, offTop) {
    let top, left;

    left = offLeft;
    top = offTop;

    crazyButton.style.top = top + 'px';
    crazyButton.style.left = left + 'px';
    crazyButton.style.animation = "none";
}
```

And we test:
![fde568eb7135dda0b81455054cc4eb37](https://dev-to-uploads.s3.amazonaws.com/i/z8qz4x7dsp2kpl72bmyh.gif)
 

Cool, we are all done!

## Conclusion

Today you learned what socket.io is, how to pass data, and how to emit & listen for messages. I hope this was helpful and you learned something today! Full project available at [my website](https://theinternetbutton.asciinaut.sh/).

Make sure to check out my other post related to this - [The JSourney: Learn with projects, not videos!](https://dev.to/denislav__/the-jsourney-learn-with-projects-not-videos-1hg1). I explain why building projects is a better way to study, instead of watching videos all day.