Construct2 can use websockets to send and receive messages between games. By using socket-io, we can use a Node.js script as the server and my modification to the socket-io plugin for Construct2 to allow the games to synchronize data between them in real-time. There are two parts to this design: the Node.js server and the Construct2 clients (the games playing).
The main part of building an online multiplayer HTML5 game is to plan:
- how the clients will communicate
- how often and what to communicate
- how much of the logic will go into the server and how much to the client.
In my sample game, I chose to have each client own a player and have the server just relay messages:
- Use string messages in the form TypeOfMessage, Parameter1, Paremeter2, Parater3, etc to communicate.
- Have the clients send their player position about 16 times a second. Whenever their player shoots, the client needs to send a message immediately.
- Almost all of the game logic will reside in the client
The Server Script
The server runs in Node.js and functions as basically a relay of messages between Construct2 clients. The server needs to run outside of Construct2 because a construct2 game cannot run as a server, i.e. it cannot use your computer to “listen” to messages. It can only connect to a websocket server (in this case Node.js) and sent/receive messages to/from it.
If you look at the source code of the example_server.js file included in my plugin, you will see that the first thing we do is to listen in port 8099:
var io = require("socket.io").listen(8099);
The next thing we do is to staet listing for connections, and if we get one, we send the connecting client an initialization message:
socket.send('I,' + mySelf + ',' + mySelf + ',' + mySelf);
The initialization message simply tells the connecting client (the C2 game) the id of his player and the initial x and y coordinates for his player. Note that the message is just a string. I chose to make my messages sent from the server formatted in the following way:
TypeOfMessage, Parameter1, Paremeter2, Parater3, etc
The parts of the message are separated by commas. Next in the server script, we use a loop to send the connecting client the positions of each of the clients (players) already connected:
socket.send('C,' + entity + ',' + entity + ',' + entity);
This message type is C, which means that the client has to Create a player (in this case the other clients have to create the new player that just connected). We will see later how the Constrcut2 clients interpret those messages. After the positions of the players are sent to the connecting client, we broadcast the to the clients already connected that a new client has arrived and its id and initial position (which was set by this script):
socket.broadcast.emit("message",'C,' + mySelf + ',' + mySelf + ',' + mySelf);
Please note that the initial position is set by the server to the same position always for simplicity, however, in your game, there is no reason why you have to do this. You could have multiple random spots and just let the server assign any of those random spots.
The next part of the server script uses socket.on("message", function (data) to start listening to any messages sent by this newly connected client. This line is different from the previous io.sockets.on("connection", function (socket) in that the later line listens to connections only not messages.
Each message sent by the client can be a UM (update position) or a S message (shoot). The server splits by comma any message sent by the client, detects what kind of message is and then relays the message to all the other clients (players). Note that if th message is a UM (update position), the server will save the position so that it can send the correct position to any new client.
Each client is a Construct2 game that use the modified websocket plugin to send messages to the server (not to the other clients).
On the start of the playing layout, we connect to the Node.js server using its IP address:
Note that the IP address could be public or a LAN address. If public, the server (node.js) must be running in a LAN whose router redirects the 8099 to the computer running the Node.js server script.
Once connected, the client listens to messages from the server. The first message it will receive is an Initialization message:
When this message arrives, C2 will create a player in the coordinates given by the server and assign the owned player the id sent by the server. Note that plugin has a special action “Split Data Received” that splits the message into its parts (element 0 is the type of message, element 1 is the ID of the player, element 2 and 3 are the X and Y positions).
The client will also receive C messages to create the other players:
Finally, the client will receive messages to update the position of the other players or to have the other players shoot:
To update the position of the own player and to notify the shooting of the own player, the Construct2 game will send messages to the Node.js server when the conditions occur:
Note that it sends its player position every 0.07 seconds. Whenever their player shoots, the client also sends a message immediately.
The above picture give you a quick overview of how the parts discussed interact with each other. Please remember that you can make your message represent anything you want, e.g.: player picks up an item, player dies, etc. However keep in mind that you should limit the amount of information flowing. Choose the most basic messages that would allow your game to run parallel. For example in my sample game, I do not have a “Died” message because I am trusting that the clients are synchronized enough that if a bullet hits a player in one client, the same bullet will hit it in the other client because the bullet was created with the same position and velocity in all the clients.
There are some tips here on how to install Node.js and socket-io in your machine.
Online multiplayer takes a lot of discipline and knowledge. I strongly recommend that you start with something basic (like a pong game where you just update positions) and then move from there.