In the previous post, I talked about how to set up Quintus and Node.js for a simple single player web game. Unfortunately, because we’re coding up a game of tag, keeping our game single player doesn’t make all that much sense.
Socket.io
Listening for connections/disconnects
We’ll write the code to monitor connections and disconnects on our server-side app.js
:
|
|
Lines 6-7: Declaring variables that are used to track the number of players and assign a unique id for each player respectively.
Lines 12-15: We wrap these socket emit events in a timeout because if a connection event was fired to the user right when they started connecting to the webpage, they wouldn’t have loaded the proper javascript files yet and the event wouldn’t do anything. A 1.5 second delay on connection gives a nice buffer time.
Line 13: This event, as denoted by socket.emit
, is only emitted to the user who connected. We can attach a javascript object as a second parameter which is accessible in the client javascript, so any data we want to send to the user from our server should be put here. In this case, we attach the unique id variable for this user.
Line 14: We also emit an event to every single user (Including the one that just joined), which serves to update the player count in the game.
Line 17-20: Here we handle the disconnect logic for the user, simply notifying all users of the app of the new player count.
Adding a player counter
When a player connects, socket.io will emit a count
event to all connected users, passing a javascript object with the count of players. Let’s create a counter in our webpage that will eventually update on player connect/disconnect.
|
|
Lines 6-16: Set up some CSS styling for our player count span.
Line 18: A span with id players
that we’ll use to update the player count with.
Adding things on connect!
Let’s update our game.js
file to add a Player
when a socket.io connected
event is received.
|
|
Line 1: Instantiate an array players
which will hold all of the Player
objects currently in the game.
Line 2: Create a socket
object that connects with our server.
Line 3: Declare the UiPlayers
variable as the element with id players
we added in index.html
just now.
Line 6: Declare a setUp
function that oversees communication with socket.
Lines 7-9: On a count
event received from the server, we update the text of the UiPlayers
variable to be the playerCount
data passed in from the server.
Line 12: Save the playerId
the server assigned to us.
Line 13: Create a new Player
object with the properties we passed in. Notice we passed in the socket object declare before.
Lines 14-15: Add our player to the stage and make the viewport follow the player. Notice we moved the logic for actually creating the player and making the viewport follow the player into the socket connected
event.
Line 22: Call the setUp
function for our stage
.
Sending information back to the server
In order for other people to see my player move, the server must send information about my player to them. In order to receive information about my player, the server needs to receive data from the client. Here’s how I do it:
|
|
Using the socket (we pass it into the player on creation) which we’ve saved as a property on our player, we emit a socket.io event called update
to the server. The second parameter of the emit event contains a javascript object where we can tell the server things about our player like position, invincibility status, id of the player, etc.
Receiving updates from players
Now that our player emits a socket update
event, we can take that data from our server and distribute it to all other players, so they can see where we move to. I added the following event listener to the server:
|
|
Now we can write our client-side code to update the other players when we receive their update
events. I start by creating a new Actor
class for other players (Note: We can’t reuse the original Player
class we wrote since every instance of the Player
class is controllable through our keyboard and each instance of the Player
sends the update
socket event after every step).
Because the Actor
class is small, I can just throw it in the player.js
file.
|
|
Notice that save for the interval function, the Actor class has almost no properties set on instantiation or step. This is because we set them ourselves when we get an update
event with all the necessary properties. This interval function destroys an Actor
when it hasn’t received any update events for three seconds. Without it, if a person were to close out of our webgame the Actors
would still persist.
Finally, we need to write some functionality that will take our updated
event data from the socket server and update the corresponding actors. I placed the following in the setUp
function:
|
|
Line 1: Declare our socket event listener for the updated
event.
Lines 2-4: Filter through our players
array for any players with the same playerId as the one being updated.
Lines 6-9: If we found a player in the players
array then update their relevant properties.
Lines 10-13: Else, we just create a new Actor
class for that player, push it onto our players
array, and insert it into the stage.
Run it!
Run your node application once again. You’ll see that if you join your server from multiple tabs, there should be players popping up for them! Movement should be updating as well, although for certain browsers like Chrome you need to keep each tab in its own window (Javascript loses focus when it’s not the current tab, so it won’t be able to update if you’re focused on another game tab in the same window). Try getting a family/friend to join the same port and they should be able to run around with you!
In my next blog post, I’ll show you how to get the tagging logic down. Keep an eye out!