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:
- Part One: Series Overview and Building a Multiplayer Game Lobby
- Part Two: Adding Users and Usernames
- Part Three: Getting a List of Online Users
- Part Four: Random Matchmaking of Users
- Part Five: Skill-based Matchmaking of Users
- Part Six: Matchmaking Algorithm: Enabling Users to Challenge Other Players
- Part Seven: Create Chatrooms and Multiple Channels On Demand Tutorial
- Part Eight: Preparing for Private Chatrooms and Refactoring via Private Channels
- Part Nine: Creating Private Chat Requests with Popup Alerts
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:
One User Calls Another
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.
How to Make Users Clickable
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.
Handshake to Establish Communication
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
if(data.type =='chat') and then access
Targeting Specific Users
Now that we’ve filtered our
type: 'chat' messages, let’s handle our
type: 'challenge' messages.
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.
Completing the Handshake
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' or
action: 'request' message is the first message broadcast. It is sent from
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
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.
Matchmaking Algorithm Demo
Check out the full matchmaking algorithm demo here or embedded below. We’ll begin organizing our code in the next chapter.