Free up to 1MM monthly messages. No credit card required.
In this tutorial, we’ll continue talking about creating multiple channels to spawn chatrooms on demand. In this case, we’ll walk you through how to enable users to spawn private chat with another user on demand. This way, users can select who they want to chat with, then initiate a private chat with that user.
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:
Now that we can spawn chatrooms on demand, let’s allow one user to spawn a new private chat on a private channel with another user.
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:
Up until our most recent tutorial, our code has been only functional. Like last time, our code this time will be object oriented. If we added the ability to spawn chatrooms to our old functional code, things would get confusing very quickly. We’ll start by converting our functional code into object oriented code. This will make it easier for us to manage user to user communications.
We’re going to make use of what’s known as the Object Constructor Pattern. Let’s start with our Alarm closure example from earlier.
What if we wanted to expose the
name variable from outside the
Alarm() function? We use the
this keyword to expose the variable outside of our function.
Notice the changes made to our last lines. Specifically how we changed
Instead of simply executing
Alarm(), we call
new_alarm = new Alarm() which assigns the instance of the function to the variable
We need to use the word
new because it instructs the the value of
this to be bound to the context of the function. If you forget to use the
new keyword, this will be assigned to the global object.
Douglas Crockford has a great writeup of the object constructor pattern,
this, private and public methods and more.
So now let’s start refactoring our old challenge example into an Object Constructor pattern.
Notice that instead of using
this directly, we assign
var self = this. This is because the
this variable will have a different value within nested functions. We want to ensure that we’re always referring to the
User context, so we store the context of
self so we can access it from inside any function.
return self; at the end of the function allows us to string function methods together. For example, we could call
We also gain a huge organizational advantage switching to an object oriented pattern. We’re able to store references to the DOM elements within the objects themselves, allowing us to modify the page without actually selecting nodes by hand.
Instead of calling
$('#' + data.uuid).remove(); we can write:
a_user has stored the DOM node in
$tpl so we can access it directly instead of looking it up.
state. Now that we keep users in objects, we can keep the value of their state as a property. This means when we need to find an opponent for matchmaking, we can avoid using the
pubnub.here_now() call. We’ll already have a list of users and their state ready!
We’re going to support an unlimited number of users, so creating objects one at a time will quickly get messy. Instead, we’ll create a factory pattern that will keep track of our
User()s in an array.
The largest change to our app are the changes to
me. Instead of
me just representing a username, we’re going to make it into an object that turns the browser window into an extension of a
We start out by assigning the variable
self to a
new User() with a
randomName(). This means
Client() will be an extended from
User() and have all it’s properties like
We add a couple more methods to the Client:
onResponse(). These handle our challenge requests and responses. We only add them to our Client instead of every User as we don’t want to accidentally challenge or respond on behalf of another user.
Also, because the
Client() extends the
User() we can still get the client username from
me.uuid. We bind to the DOM events inside of the
App() object and then act on behalf of the
me object when fired.
Last, we create an
App() object to initialize our application and handle incoming traffic.
It’s worth noting a couple additional changes to scope.
me turned into a global variable as is
Users and some of our global template elements. The function
randomName() is still available globally and our skill generator has been turned into
Put it all together and we have the following.
Check out the live demo below. It looks and behaves exactly as our previous example did, but the code has been organized into an object oriented pattern.
In our next blog post, we’ll talk about how to spawn private chatroom popups.
Take a look at the top trends that are the most effective in attracting customers and reducing churn, and how you can incorporate...
Comparing the major game engines: Unity vs Unreal Engine vs Corona SDK vs GameMaker Studio, including the benefits and cons of...
Sockets (aka socket programming) enable programs to send and receive data, bi-directionally, at any given moment. This tutorial...