We’ve updated our SDKs, and this code is now deprecated.
Good news is we’ve written a comprehensive guide to building a multiplayer game. Check it out!
Let’s chat about multiplayer matchmaking algorithms. In this blog post, we’ll cover how to enable multiplayer users to challenge other players. In our last two blog posts on multiplayer matchmaking, we showed you how to build random matchmaking and skill-based matchmaking.
We’ve now covered both building a multiplayer game lobby with a chatroom and the different ways we can use matchmaking to connect two different users. Here’s what we’ve covered so far:
This blog post is Part Six of PubNub Developer Evangelist Ian Jennings‘s series on creating a multiplayer game with JavaScript.
You’ll first need to sign up for a PubNub account. Once you sign up, you can get your unique PubNub keys in the PubNub Developer Portal. Once you have, clone the GitHub repository, and enter your unique PubNub keys on the PubNub initialization, for example:
Matchmaking is great, but what if you want to play against a specific opponent? Let’s add the ability to challenge another online user.
This “challenge” pattern will bring us the same synchronization functionality found in many applications. There are several uses for a matchmaking algorithm: pairing two parties on a phone call, pairing a driver and passenger, or pairing users to make edits to a document in a collaborative environment. For example, the same code we’ll write today could arrange a video call for Skype or Google Hangouts or hail a cab through Lyft or Sidecar.
The first thing we’re going to do is add the ability to select a user from the list of#online-users
. We’ll add a basic click handler to the user elements.
We’ll also add some additional CSS to show that the users are now clickable.
Great, now instead of just firing an alert()
on click, we’ll pubnub.publish()
our challenge. This will begin the handshake process.
Handshaking is an automated process of negotiation that dynamically sets parameters of a communications channel established between two entities before normal communication over the channel begins.
Notice how the message
object has changed yet again. It is now one level deeper.
In the previous chapters we only had one type of message, a chat message. Every chat message would be seen by every user so we didn’t need to do much filter.
Now we have multiple types of messages being broadcast over the same channel. There are chat messages, challenge requests, and challenge responses.
This is why we standardize the message object by adding a type
property. This let’s us know how to act upon receiving different types of messages.
The next thing we do is add a payload
property which will act as a bucket for the rest of our message information.
Making this change to the message packet means that we need to update our old chat code triggered when a message is received. Now instead of accessing for data.username
we check if(data.type =='chat')
and then access data.payload.username
instead.
Now that we’ve filtered our type: 'chat'
messages, let’s handle our type: 'challenge'
messages.
Notice the target
and uuid
properties in the message object from the $new_user.click()
function above.
Since all of our messages are sent over the same channel, how do we know who is challenging who? uuid
will tell us who is sending the message, and target
will tell us who is intended to receive the message.
In addition to filtering our message based on type: 'challenge'
, we only act on messages intended for us by ensuring payload.target == me
.
Once we receive a challenge, we’ve completed the first part of the handshake process. One user challenges another, and the other user receives the challenge.
However, it wouldn’t be fair to act upon the challenge so soon. We need to give the user who is receiving the challenge the ability to accept or deny it.
We filter upon the payload.action
to divide the types of messages again. Now, messages with type: 'challenge'
are also filtered between action: 'request'
oraction: 'response'
.
The action: 'request'
message is the first message broadcast. It is sent from uuid
totarget
.
When the target
user receives type: 'request'
, they are shown a prompt. The payload is then broadcast with type: 'response'
and “action“` equal to the result of the prompt (boolean);
Check out the request and response code below.
It’s also important to note that the values of uuid
and target
in the response are the reverse of values when the request is made. It could be represented simply as:
Because challenges are public we could log all challenges to the chat room if we wanted. In this case we simply choose to ignore any challenge that is not sent to us.
If we wanted challenges to remain private, we could create private channels for each user and send challenges through them. We’ll cover private user channels later in the guide.
Check out the full matchmaking algorithm demo here or embedded below. We’ll begin organizing our code in the next chapter.
See the Pen Memewarz – Challenge by Ian Jennings (@ianjennings) on CodePen.0
There are common underlying technologies for a dating app, and in this post, we’ll talk about the major technologies and designs...
Michael Carroll
How to use geohashing, JavaScript, Google Maps API, and BART API to build a real-time public transit schedule app.
Michael Carroll
How to track and stream real-time vehicle location on a live-updating map using EON, JavaScript, and the Mapbox API.
Michael Carroll