Click here to Skip to main content
Click here to Skip to main content
Go to top

Pixelreka! - Real Time Game with TogetherJS JavaScript Library

, 22 Dec 2013
Rate this:
Please Sign up or sign in to vote.
Build a collaborative game (or any other app) with Mozilla's Real Time Collaboration Library

Introduction

A few months ago, Mozilla Foundation released TogetherJS, a powerful collaboration tool: a JavaScript library which, once added to your website, could establish connections between users in real time.

Although the technology is not new (just to name a few, since few years ago we have Web Sockets for full-duplex communication channels and SignalR.Net which also works when web sockets are not available), TogetherJS provides a rich set of out-of-the-box features for real-time collaboration, such as the standardized dialogs, the ability to change your name and avatar and also a built-in chat. So, Immediately I recognized the potential of such library and that's how the Pixelreka game was conceived.

System Requirements

Since this project relies solely on JavaScript, there will be no need for compiling code. If you want to modify and test it, then any good code editor will be enough, such as Notepad++, Sublime Text or even Visual Studio Express 2012 for Web.

TogetherJS

Getting started with TogetherJS is as easy as including the following script tag in your HTML page:

            <script src="https://togetherjs.com/togetherjs-min.js"></script>
        

Can it be that simple? Yes, it can. And you can put the above tag anywhere in your HTML.

The centerpiece of TogetherJS is the hub. Using WebSocket protocol, the hub is a server to which the clients are connected, and which receives and broadcasts messages coming from/delivered to the clients connected in the same session. In doing so, the messages are preserved and redistributed exactly as they arrive.

TogetherJS works by redistributing messages passed by the browsers participating in the same session through the hub. TogetherJS doesn't require clients to stay in the exactly same page, but since Pixelreka is a single-page application, you might think otherwise.

Once the connection is established between the client browsers and the hub, some out-of-the-box real-time features are automatically put to action. For example, whenever one of the client participants move the browser, a message is sent via websockets to the hub, which in turn broadcasts that message untouched to the other client participants.

Now that we managed to reference the TogetherJS JavaScript library in our code, it is required that each client agrees with the connection. It could be done automatically by our application and transparent to the user, but instead we create a button inviting the user to join the game.

                <input type="button" class="start-togetherjs btn btn-large btn-success" onclick="initializeTogetherJS(); return false;" 
                style="display: none;" value="Start Pixelreka!" />
            
                function initializeTogetherJS() {
                    TogetherJS(this);
                }
            

When the user starts Pixelreka, he or she enters the single page application, showing the central panel containg the big-sized pixel drawing board, along with the color palette at the left, the challenge word in the bottom, and a "shuffle" button. In this pixel drawing board he or she will have to (guess what?) draw some picture representing the challenge word, so that other participants will have to guess it correctly. The suffle button if for when the player finds it very difficult to draw or doesn't know the meaning of the word, so another challenge word can be immediately picked up.

You can see that the above picture shows a panel at the right edge, and that is automatically provided by TogetherJS for your page. It has four buttons and they are detailed as follows:

  • This is you: this is where you configure your name, avatar (i.e. your photo), provide feedback to Mozilla foundation and exit the TogetherJS session.
  • Invite a friend: once pushed, this button will display a tray with a url that you would like to send to a friend so that you both could play together.
  • Audio Chat: use microphone/speakers to communicate with other session participants through the Web RTC technology. Web RTC is a nice feature, but only implemented by Chrome and Firefox (no Internet Explorer support so far).
  • Chat: a regular and simple text chat.

Updating an avatar is quite easy. Just chose a file in your local file system and you're done.

Inviting a friend for your session requires you only a copy-and-paste of the url provided by TogetherJS. See how the session identity is embedded at the end of the url.

When your friend receives the url of the game session, he or she will immediately see the game board with your avatar, and will be asked to join the ongoing session.

Configuring Communication

It's a relief to know that TogetherJS will help you us with all the infrastructure needed for communication. All we have to do is configure exactly what messages are to be passed between the session participants and what functions are to be invoked when receiving such messages.

The

Pixelreka

application is quite simple, and we rely on only three kinds of messages:

  1. editor-started: this message is triggered when a new "editor" starts drawing. This means that the participants receiving the message are those ones who have to guess the drawing correctly. The message has the following components:
    • userId, userIdentityId: the editor's IDs generated by TogetherJS infrastructure.
    • avatar: the image URL of the editor user.
    • name: the editor's name.
    • category: the category of the word the editor must draw.
  2. pixel-set: this message is sent everytime the editor changes a pixel color in the drawing canvas. Every session includes a lot of drawing, so this message is expected to be broadcast many, many times. This is where people participating in the game start guessing.
    • pixelId: the pixel id, varying from 0 to 255. This pixel refers to the bitmap position in the pixelated drawing canvas.
    • colorIndex: the color index, defined by the drawing color palette.
  3. new-guess: as the drawing becomes more complete and clear, the participants will start guessing, and this message is sent with the following parameters:
      userId: the id of the user making the guess.
      guess: the word being guessed.

It should be noticed that the above list refers only to the custom communication that we have to set up for our application to work correctly. At th same time there are many more messages coming and going between participants via the Together JS hub, such as mouse movements, clicks, text box changes, but these ones are provided out-of-the-box and automatically by the TogetherJS library so that we don't have to worry about them.

The following code shows how to set up these messages:

    setupCommunication: function () {
        var self = this;
        TogetherJS.hub.on("editor-started", function (msg) {
            if (self.currentPlayerIdentityId() != msg.userIdentityId) {
                var guessUser = TogetherJS.require("peers").getPeer(msg.userId);
                self.currentPlayerIdentityId(guessUser.userIdentityId);
                self.currentPlayerName(guessUser.name);
                self.currentPlayerAvatar(guessUser.avatar);
            }
        });
        TogetherJS.hub.on("pixel-set", function (msg) {
            self.pixels()[msg.pixelId].colorIndex(msg.colorIndex);
        });
        TogetherJS.hub.on("new-guess", function (msg) {
            var guessUser = TogetherJS.require("peers").getPeer(msg.userId);
            var callback = function () {
            };
            newGuess(guessUser, msg.guess, callback)
        });
    },
            

The "editor-started" message

As seen above, the "editor-started" message is broadcast when the new editor (the person to draw something on the game canvas) is set. There is a couple of situations when this message is sent. The first one is when the player clicks "Start" button and the TogetherJS session is initialized:

    cmdStart: function () {
        this.startEditor();
    },
            

The second one is invoked when the user reloads the page, thus he/she is automatically reentered in the TogetherJS session. Notice how the TogetherJSConfig_on_ready function is declared to handle the reentering of the participant:

TogetherJSConfig_on_ready = function () {
    startGame();
};
.
.
.
var Game = function () {
    this.initialize();
}
$.extend(Game.prototype, {
...
    initialize: function () {
        ...
        this.viewModel.startEditor();
        ...
    },
...
});
            

And finally the startEditor class itself, which among other things sends the message via the send method of the TogetherJS object.

startEditor: function () {
    TogetherJS.send({
        type: 'editor-started',
        userId: TogetherJS.require("peers").Self.id,
        userIdentityId: TogetherJS.require("peers").Self.identityId,
        avatar: TogetherJS.require("peers").Self.avatar,
        name: TogetherJS.require("peers").Self.name,
        category: self.category
    });
    this.currentPlayerIdentityId(TogetherJS.require("peers").Self.identityId);
    this.currentPlayerName(TogetherJS.require("peers").Self.name);
    this.currentPlayerAvatar(TogetherJS.require("peers").Self.avatar);
},
            

The "pixel-set" message

The "pixel-set" message is what enables other participants to see the drawing process.

When the user clicks the drawing canvas, he or she triggers the setPixel function of the PixelViewModel. The message is then broadcast, informing who is drawing and where in the drawing canvas the given color is being painted.

var PixelViewModel = function (index, col, row, even, colorIndex) {
    this.initialize(index, col, row, even, colorIndex);
};
$.extend(PixelViewModel.prototype, {
    .
    .
    .
    setPixel: function (colorIndex) {
        var self = this;
        if (gameViewModel.isMouseDown) {
            if (self.colorIndex() != colorIndex) {
                self.colorIndex(colorIndex);
                if (!game)
                    startGame();
                TogetherJS.send({
                    type: 'pixel-set',
                    userId: TogetherJS.require("peers").Self.id,
                    userIdentityId: TogetherJS.require("peers").Self.identityId,
                    pixelId: self.index(),
                    colorIndex: colorIndex
                });
            }
        }
    }
});
            

The "new-guess" message

As the drawing becomes more clear, the players will start making guesses, and the new-guess message is sent when the users fills in the txtGuess input box and pushes the Send button.

cmdSend: function () {
    this.send();
},
send: function () {
    var self = this;
    TogetherJS.send({
        type: 'new-guess',
        userId: TogetherJS.require("peers").Self.id,
        userIdentityId: TogetherJS.require("peers").Self.identityId,
        guess: self.txtGuess()
    });
},
            

Game Play

As the connections are established between participants, the editor player is ready to start drawing and the other participants are ready to start guessing. The drawing in one side is shown almost immediately on the other browsers.

In the example below, Kermit and Animal have both entered the same session.

Notice how they see one another in the right panel that is provied by TogetherJS:

But the drawing board is a bit different for the both of them. Animal is drawing on the left board, and that's why he's holding a brush, while Kermit is trying to guess his drawing, and he sees a top right avatar indicating that it's Animal's turn to draw:

Then Animal starts drawing and Kermit immediately sees that drawing happening in his browser:

Even though the drawing board is a low-res, 16x16 bitmap, sometimes using a brush as wide as one pixel is a lot of work, especially when filling regions (such as painting an elephant). In these occasions, a wider brush would be much more convenient for the task:

Using different colors also help making the drawing more clear:

Now that Kermit finally figured out what Animal's drawing was about, he fills in the "guess" text box:

When Kermit sends his guess, this is what is popped up on Animal's browser.

Since the game is not complete, it ends here. I know, you wanted more. But for the goal of demonstrating TogetherJS, this might be enough. You are free to extend the game, implement scoreboards, implement turn management, badges, sharing game results on Facebook and Twitter and what else your imagination allows.

Final Considerations

Web based real-time communication is getting more powerful than ever. Very soon there will be in the landscape a commoditization of infrastructure communication technologies that not long ago were available only for the advanced developer. We should be thankful to the efforts made by TogetherJS team to bring us such high level tools, allowing us to save time and focus on our own core application features.

Thanks a lot for the reading, and please feel free to leave a comment regarding the article and the accompanying code.

History

  • 2013-12-22: Initial version.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Marcelo Ricardo de Oliveira
Software Developer
Brazil Brazil
Marcelo Ricardo de Oliveira is a senior software developer who lives with his lovely wife Luciana and his little buddy and stepson Kauê in Guarulhos, Brazil, is co-founder of the Brazilian TV Guide TV Map and currently works for ILang Educação.
 
He is often working with serious, enterprise projects, although in spare time he's trying to write fun Code Project articles involving WPF, Silverlight, XNA, HTML5 canvas, Windows Phone app development, game development and music.
 
Published Windows Phone apps:
 
 
Awards:
 
CodeProject MVP 2012
CodeProject MVP 2011
 
Best Web Dev article of March 2013
Best Web Dev article of August 2012
Best Web Dev article of May 2012
Best Mobile article of January 2012
Best Mobile article of December 2011
Best Mobile article of October 2011
Best Web Dev article of September 2011
Best Web Dev article of August 2011
HTML5 / CSS3 Competition - Second Prize
Best ASP.NET article of June 2011
Best ASP.NET article of May 2011
Best ASP.NET article of April 2011
Best C# article of November 2010
Best overall article of November 2010
Best C# article of October 2010
Best C# article of September 2010
Best overall article of September 2010
Best overall article of February 2010
Best C# article of November 2009

Comments and Discussions

 
QuestionAnother outstanding article! PinprofessionalCésar de Souza23-Dec-13 13:42 
Questionnice PinmvpSacha Barber22-Dec-13 9:42 
AnswerRe: nice PinmvpMarcelo Ricardo de Oliveira22-Dec-13 14:09 
GeneralRe: nice PinmvpSacha Barber23-Dec-13 2:57 
GeneralRe: nice Pinmemberbxb5-Jan-14 23:22 
QuestionNice article Marcelo! PinmemberVolynsky Alex22-Dec-13 9:40 
AnswerRe: Nice article Marcelo! PinmvpMarcelo Ricardo de Oliveira22-Dec-13 14:06 
GeneralRe: Nice article Marcelo! PinmemberVolynsky Alex23-Dec-13 8:45 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web03 | 2.8.140916.1 | Last Updated 22 Dec 2013
Article Copyright 2013 by Marcelo Ricardo de Oliveira
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid