Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Lightweight Multiplayer HTML5 Games with PubNub


Published on

Can a web browser be used as a platform for serious gaming? Here at PubNub, we intended to find out, and decided to experiment with an HTML5 game engine.

  • Be the first to comment

  • Be the first to like this

Lightweight Multiplayer HTML5 Games with PubNub

  1. 1. LightweightMultiplayerHTML5 Gameswith PubNuband melonJSBy Jay Oster
  2. 2. Can a web browser be used as a platform for serious gaming? Here atPubNub, we intended to find out, and decided to experiment with anHTML5 game engine. melonJS is the tool of choice because it’slightweight, runs well on mobile, and is very easy to use. One questionthat always comes up on the melonJS forum is the best way to useNode.js/ to build multiplayer games. In this article, we will beusing PubNub, but many of the techniques can be applied to aswell.For this experiment, we start with the platformer demo that ships withthe melonJS 0.9.7 source code, and transform it into a multiplayer gamewith just a few extra lines of code. And all without any servers! This is onlypossible with the power provided by PubNub.Want to see the end result? Check it out here. We’ll walk you through howto add multiplayer support to your own game below:
  3. 3. Download melonJSFirst step, clone the git repository and checkout the 0.9.7 tag:Next, you’ll want to follow the build instructions to build the library. And you can test the vanillaplatformer demo by launching an HTTP server with Python:Now visit the URL in your favorite web browser:It’s a very simple game demo, with a handful of enemies and two maps. However, we wantmultiplayer support as well. What we started with is a simple module to handle the multiplayercommunications:$ git clone$ cd melonJS$ git checkout 0.9.7$ python –m SimpleHTTPServerhttp://localhost:8000/examples/platformer/
  4. 4. mp.jsvar Multiplayer = Object.extend({init : function (new_player) {this.pubnub = PUBNUB.init({publish_key : "demo",subscribe_key : "demo"});this.new_player = new_player;// Record my UUID, so I dont process my own messagesthis.UUID = this.pubnub.uuid();// Listen for incoming messagesthis.pubnub.subscribe({channel : "PubNub-melonJS-demo",message : this.handleMessage.bind(this)});},handleMessage : function (msg) {// Did I send this message?if (msg.UUID === this.UUID)return;// Get a reference to the object for the player thatsent// this messagevar obj =;if (obj.length){obj = obj[0];}else {var x = obj.pos && obj.pos.x || 50;var y = obj.pos && obj.pos.y || 50;obj = this.new_player(x, y); = msg.UUID;}// Route messageswitch (msg.action) {case "update":// Position updateobj.pos.setV(msg.pos);obj.vel.setV(msg.vel);break;// TODO: Define more actions here}},sendMessage : function (msg) {msg.UUID = this.UUID;this.pubnub.publish({channel : "PubNub-melonJS-demo",message : msg});}});
  5. 5. mp.jsThis class has a constructor and two methods; the constructor takes one callback, andthe sendMessage() method is the one we’ll be using to send game state updates. This module alsodoes some useful things like creating new player objects, and handling player position updates. Weplaced this file (mp.js) into the platformer directory, and included it within index.html (along withpubnub-3.4.5-min.js)
  6. 6. Creating a new Multiplayer objectTo initialize the Multiplayer object, we added a few lines after the level has been loaded, around line104:// Instantiate the Multiplayer = new Multiplayer(function (x, y) {// Create a new player objectvar obj = me.entityPool.newInstanceOf("mainplayer",x, y, {spritewidth : 72,spriteheight : 98,isMP : true});, 4);;return obj;});This creates the object, placing a reference into the game namespace as , and passes a callback function thatwill create new player objects when we receive messages from other players we haven’t seen before.That isMP : true line is important! It will be used later to determine whether the player object is Keyboard-controlled, orcontrolled by messages from the network.
  7. 7. Creating a new Multiplayer objectSide note: to make testing easier, you can disable the “automatic pause” feature when navigatingaway from the browser window. We added the following line just before the call to inmain.js:me.sys.pauseOnBlur = false;
  8. 8. Turning the PlayerEntity object into a Multi-PlayerEntity ObjectNow we’re ready to hack the PlayerEntity object to work in a multiplayer environment, sendingposition updates, and ignoring the keyboard input for the isMP entities. Starting in entities.js at line 25,we added two new properties:this.isMP = settings.isMP;this.step = 0;Then we changed the following lines to be conditional on the value of the isMP property. The viewportfollow and key bindings should be skipped if the entity is a multiplayer object:if (!this.isMP) {// set the display around our position/* ... snip */// enable keyboard/* ... snip */}
  9. 9. Turning the PlayerEntity object into a Multi-PlayerEntity ObjectThe original code has been snipped from the example above, but it should be pretty obvious whatneeds to be changed here.In the PlayerEntity.update() method, there are a few things that also need to be made conditional onthe value of isMP. This first checks the key status:if (!this.isMP) {if (me.input.isKeyPressed(left)) {/* ... snip */}if (me.input.isKeyPressed(jump)) {/* ... snip */}}
  10. 10. Turning the PlayerEntity object into a Multi-PlayerEntity ObjectThere’s also a call to that reloads the level when the player falls into a hole. We could make thatconditional too, if we don’t want to reload the level when other players fall in.And finally, there’s a comment at the end of the method about checking if the player has moved. This is the perfect hook for sending outplayer position updates to other players! We added the following code just before the call to this.parent() :if (this.vel.x !== 0)this.flipX(this.vel.x < 0);if (!this.isMP) {// Check if its time to send a messageif (this.step == 0) {{action : "update",pos : {x : this.pos.x,y : this.pos.y},vel : {x : this.vel.x,y : this.vel.y}});}if (this.step++ > 3)this.step = 0;}The first two lines will fix the “direction” of the player object when it isupdated by a message from the network.The rest contains a basic counter to prevent sending messages toofast, and the final message publish that other players will receive.
  11. 11. Play It Online!The final demo can be played online now!And you can also have a peek at the fullpatch here. A much better approachwould be separating control logic entirelyfrom the entity. But in this case, the demoserves its purpose. Maybe next time, wecan work on synchronizing more of thegame state, like enemy positions andindividual score counters!