BrowserQuest’s Event Handling

This time I want to look at how BrowserQuest handles event happening and how reactions are triggered.

(Last time, I did a quick write up on animation in BrowserQuest.)

Just from playing through the game, you can see that a few things happen when you die: the you explode in a puff of smoke, and the ‘revive’ screen pops up. Lets see how they’re throwing that event.

You are dead.
You are dead.

The die method in the Character object is the one that handles our player dieing, and it’s pretty simple: stop trying to attack whatever we were attacking, and mark us as dead. The bit we’re interested in this post though is the callback.

die: function() {
    this.isDead = true;

    if(this.death_callback) {

this.death_callback is a variable which is set in the onDeath method. I’m not all that sure why this is a public variable, but public variables seem to be the common way of storing data throughout the project. BrowserQuest was never intended to be an example of clean coding standards, so I won’t hold it against them. But this is a problem since those public properties could be relied upon existing by other developers (either in or outside of the dev team). This makes refactoring later on really hard if you don’t want to risk having unintended side affects of changing these properties.

Calling the event onDeath is something I hadn’t thought of doing. The events is like any other that we come across in JavaScript: onClick, onFocus, and the like. So it makes a lot of sense for it to start with the ‘on’ prefix.

Something that limits this feature is that there can only be one callback. That’s very different to how we think of other events. Usually you can bind as many actions as you like to onClick so you’d expect the same here, but it seems that you can only have one callback per event in this system. It’s possible that this feature was never added because they didn’t think they needed it. You can see that they don’t need it by running a grep on “onDeath” and there’s only one place it’s used. (For the Character object at least.) Why waste time on implementing a fancy event system with multiple callbacks when you just need one?

Strangely though, there is another onDeath-like event which gets thrown but is handled by the game class, rather than the character. When the character dies, if you have the credits open, they should be replaced with with “revive” screen. (Code here.) I’m not sure why you wouldn’t want to just bind that code to your already existing event.

In my demo code, I made an array of elements who wanted to listen to a certain event, like ‘onKeyDown’ and then passed the event to each of those objects via their own onKeyDown method. I haven’t stress tested this at all, since there wasn’t any complicated code to be processing. I don’t think that there will be much of a difference in performance by storing an array of callbacks though.

It’s becoming clear that drawing from BrowserQuest alone for ideas of architecture won’t be enough, so I’m going to be looking at other games where the source is available in the near future to look into other ways.

Playing MP3 Files In Every Browser

I’ve been looking into various ways of being able to playing MP3 files within the browser, trying to avoid using Flash. Spoiler alert: You can’t do it just yet.

I’ve ended up using another player called jPlayer. (Demo on my prototype page.) It’s a jQuery library which uses HTML5 where ever possible but is able to fall back to Flash if it’s needed, like in Firefox.

The Flash player is invisible when you end up using it, and you control it entirely through the Javascript, which means your UI can be however you want it to look.

I was raving about jsMad, but it doesn’t look like it’s up to the task just yet. The people behind it are planning to spend more time on it in the future though, so that’s definitely exciting.

GBCanvas: A canvas experiment

I’m pretty sure my body doesn’t work on a 24 hour day cycle. I went to bed around 2300 two nights ago, and got up around seven. Though I’d been lying in bed awake, trying to sleep for much longer. I say I got about five or six hours sleep that night. I went to bed at ten tonight, and was awake by two. I feel I could stay awake until tonight now. I’m not tired or anything. Maybe so little sleep has just become a habit.

My sleep schedule isn’t why I’m here.

I’m doing some tests with the canvas element, and decided to make a class for it. You can see it over at the GBCanvas github I set up for it. (I’ve never used github. Just heard a lot about it.) The code is kinda broken at the moment though.

The class is based on the idea of pseudo-pixels, where you have a 300×300 canvas, and can set it to have ten rows and twelve columns. Then you can manipulate each of those segments, which I’ve decided to call pixels. The “GB” comes from Gameboy, because I figured it’d be cool to remake Zelda with canvas.

I want to add an edit mode so the user could do something like

$(document).ready (function () {
  var canvas = new gbCanvas ('canvasid1');
  canvas.editModeOn (true);

Which would allow clicking of a pixel and it fills it with a chosen colour. I  mostly want this feature so I can create pixel art, and then get the raw data:image/png data, which I can import into the project whenever. I’m aware I could just create sprites in Paint or something and import the file, but I don’t want to. I’m fond of imposing restrictions stubbornly unto myself.

After a few rethinks, I figured it would be fair simple to just bind a click event to the canvas

//  Turns on edit mode so onclicks are registered and bubbled
this.editModeOn = function (mode) {
  if (mode) {
    //  .click is a jquery thing (this.editModeClick);

And then working out which pixel was clicked, and filling it with colour

  this.editModeClick = function (event) {
  //  getSelectPoint just returns an array with the X and Y coord of the click
  //  relative to the top left of the image (to avoid problems with scrolling)
  clickPoints = getSelectionPoint (event, this.canvasID);
  console.log (clickPoints);
  //  Work out which "pixel" they just clicked
  var coordWidth = parseInt (clickPoints[0] / pixelWidth);
  var coordLength = parseInt (clickPoints[1] / pixelHeight);
  console.log (coordWidth + ', ' + coordLength);
  this.colourPixel (coordWidth, corrdLength);

This doesn’t seem to work because the event is rarely passed. It is sometimes, but hardly ever. The function is bound correctly. It’s entirely a problem with the event being passed – something I’ve always had trouble with if I’m honest…

Update: Ladies and gents, do yourself a favour and check all your variables before you go bitching on your blog about your code not working. The event was being passed fine. The problem with my code is that since it’s a function that’s being bound to an event, it effectively loses it’s place in the instance of the class, so it no longer has access to the this variable.

My problem was that this.cavasID was undefined.

So, I fix that by simply passing it “this”. Changing the bound event function to something like this:

this.editModeClick = function (event, _this) {
  console.log (event);
  console.log (_this);
  clickPoints = getSelectionPoint (event, _this.canvasID);
  console.log (clickPoints);
  //  Work out which "pixel" they just clicked
  var coordWidth = parseInt (clickPoints[0] / _this.pixelWidth);
  var coordLength = parseInt (clickPoints[1] / _this.pixelHeight);
  console.log (coordWidth + ', ' + coordLength);
  _this.colourPixel (coordWidth, corrdLength);

That’s all well and good, but now I’m confused as to how to bind it… (this.editModeClick (event, this));

The event needs to be the first argument, but I’ve no idea how to pass the event here… That obviously doesn’t work (event is undeclared).

Edit: Of course it was something ridiculously simple.

var self = this; (function (event) { self.editModeClick (event, self) } );