Palagpat Coding

Fun with JavaScript, HTML5 game design, and the occasional outbreak of seriousness

Let's Make a Canvas Library: States

Tuesday, January 15, 2013

Welcome to another edition of Let's Make a Canvas Library, our funkalicious tutorial series all about the basics of building a personal code library for making neat stuff with HTML5 Canvas.

(As always, the aim of this series is primarily educational, not to build an amazing library that everyone and their dog is going to want to use. But for anyone interested in following along, or anyone who likes the API we're building and wants to use it, it's available for forking and download on my Github account as TangleJS.)

Today we're going to talk about state machines.

State of the State

One of the most useful things I learned in my first semester of college computer science (back when dinosaurs roamed the earth and CS 121 used Pascal as its introductory language) was the concept of the Finite-state machine (FSM for short). To oversimplify, an FSM is a set of program states and a set of transition rules for moving between them. A state machine can only be in one state at a time, and its current state determines how it reacts to any inputs it receives.

As a simple example, the Wikipedia entry for FSMs describes a state machine that models the operation of the humble turnstile, like you might see at a state fair. A turnstile has two basic states, locked and unlocked, and two rules for transitioning between them: a coin will move the turnstile from its locked state to its unlocked state, and pushing the arm to pass through the turnstile moves it from the unlocked state back to locked again. Note that putting more coins into a turnstile that is already unlocked simply keeps it unlocked, and the act of pushing on a locked turnstile similarly doesn't cause it to change its state (i.e. it stays locked):

Transition diagram for a finite state machine modeling a turnstile

Simple state diagram for a turnstile. Original image by Chetvorno, retrieved from Wikimedia Commons

Another common way to visualize a state machine is via a state transition table, like so:

Initial StateInputs
coinpush
LockedUnlocked-
Unlocked-Locked
State transition table for a simple turnstile

In this kind of table, every state is listed, along with every possible input, and for each combination of current state and input that cause a state transition, the new state is listed. So far so good?

State of Play

“So,” I hear you asking, “What does this have to do with games or canvas...?”

Quite a lot, it turns out. First, your game itself will likely have a state machine (with states like loading, title screen, options menu, playing, paused, and game over):

Initial StateInputs
Enter key"assets loaded" event"Player die" event
Loading-Title-
TitlePlaying--
PlayingPaused-Game Over
PausedPlaying--
Game OverTitle--
State transition table for basic game logic

In this hypothetical game logic, the Loading state doesn't handle any input at all, the Title state allows you to press Enter and start playing the game, and that same key input allows you to switch back and forth between the Playing and Paused states. The Playing state also handles a "player died" event, which causes the game to go to a Game Over state.

Likewise, your game will probably have entities (more on this in a future article) such as a player, obstacles, and enemies, and each of these may have its own state machine. Take, for example, this overly-simplified (and abbreviated) state machine for the main character in a side-scrolling platformer game (think Super Mario):

Initial StateInputs
Up arrowRight arrow"state end" event"touch enemy" event
IdleJump upRun forward-Die
Jump Up-Jump ForwardFallDie
Jump Forward--Fall ForwardDie
FallDouble JumpFall ForwardIdleSquash enemy
Fall ForwardDouble Jump-IdleSquash enemy
Run ForwardJump Forward-IdleDie
Die--Trigger "player die" event-
State transition table for a platformer hero

You may have noticed that I've been including a couple of different kinds of inputs in these state transition tables: direct user inputs, such as the player pressing a key on the keyboard, and other, more abstract events such as "player die" and "state end".

At this point in the article, I originally went on a several-paragraph tangent about how complicated input and event handling are, when I realized that the subject is complex enough it deserves its own blog post. So for now, let's just assume our state machines have a fixed set of inputs (some user-driven, others event-driven), and we'll save the actual capture of those inputs for another day.

State of Control

It's pretty simple to start using the "state machine" paradigm in your JavaScript code. A naive, ad-hoc approach might look something like this:

  var state = 0;
  var assets = new AssetCache(),
      canvas = document.querySelector('canvas'),
      context = canvas.getContext('2d');

  /* (specify assets to load) */

  function _update() {
    switch(state) {
      case 0: // loading
        if (assets.ready()) changeState(1);
        break;

      case 1: // title
        // (check user inputs and change state accordingly)
        break;

      /* logic for the rest of the states */

      default:
        break;
    }
  }

  function _render() {
    switch(state) {
      case 0: // loading
        context.fillStyle = "#ffffff";
        context.fillText('Loading...', 100, 175);
        break;

      case 1: // title
        var imgSplash = assets.getAsset('title');
        if (imgSplash) {
          context.drawImage(imgSplash, 0,0, 640,480);
        }
        break;

      /* rendering code for other states */

      default:
        break;
    }
  }

  function changeState(stateNum) {
    console.log( "Entered state", stateNum );
    state = stateNum;
  }

  // set up main loops
  Tangle.init(_update, _render);
  Tangle.play();

This works fine, and I built my first couple of game projects using this approach. It just starts to feel a little copy/paste-y after a while, and any process involving copy/paste of big chunks of code is going to be susceptible to error.

It also violates the DRY principle, because you've got multiple switch statements (one for update() and one for render()), and are spreading the logic for your states across (at least) those two functions.

If we were to abstract this into a reusable StateManager class, it might look something like this:

  var assets = new AssetCache(),
      states = new StateManager(),
      canvas = document.querySelector('canvas'),
      context = canvas.getContext('2d');

  /* (specify assets to load) */

  states.addState({
    id: 0, title: 'Loading',
    tick: function(me) {
      // If all assets are loaded, return 1 to tell 
      // StateManager to change to state 1. No change otherwise.
      return (me.assets.ready()) ? 1 : null;
    },
    render: function(me, ctx) {
      ctx.fillStyle = "#ffffff";
      ctx.fillText('Loading...', 100, 175);
    }
  }); // end of state 0
  
  states.addState({
    id: 1, title: 'Title',
    tick: function(me) { /* update any title entities */ },
    render: function(me, ctx) {
      var imgSplash = me.assets.getAsset('title');
      if (imgSplash) {
        ctx.drawImage(imgSplash, 0,0, 640,480);
      }
    }
  }); // end of state 1

  // (other states omitted)

  // StateManager event callbacks
  function stateChange(data) {
    console.log( "Entered state", data.id, ":", data.title );
  }
  states.events.changeState.watch(stateChange);

  
  // set up main loops
  function _update() { states.tick(this); }
  function _render() { states.render(this, _context); }
  Tangle.init(_update, _render);
  Tangle.play();

So now each state's logic is in a single place, and if you wanted to, you could even externalize each state definition into its own .js file, if they get big enough to be unwieldy. In most cases like this, the game's update() and render() loops just defer to the StateManager's tick() and render() methods, making the main Game.js code a lot more streamlined.

Another approach might be to make this a functional mixin instead of a creatable class, if you prefer that coding style. Either way, the point is to encapsulate your state logic and make states a little more self-contained.

State of the Art*

Finally, let's look at the demo! As in the previous articles in the series, I've created a simple demo that leverages Statemanager in conjunction with the parts we've already built (AssetCache and Tangle Core) to show how they can be used to start fleshing out some actual game logic.

(Maybe next time we'll have enough building blocks in place to actually make something interesting!)

As was the case with the last few components we've built, StateManager can be used in a variety of applications, canvas or no canvas, and should work in pretty much any browser that's not a pre-version-8 Internet Explorer.

Next time we'll take more time talking about how to capture and deal with user inputs and game events. See you then!

Resources

Let's Make a Canvas Library: Game Loop

Sunday, January 6, 2013

And... hiatus is over! Sorry for the delay, it's been a crazy Autumn.

Welcome back to Let's Make a Canvas Library, our tutorial series focused on the principles of building a good personal code library for writing games and other cool stuff with HTML5 Canvas. As a reminder, last time I said we'd cover:

“the basics of building a game loop, and actually use AssetCache to build something interesting.”

So, let's talk about game loops.

(remember, my goal with this series is mainly educational, not to build the jQuery of game libraries. But for anyone interested in following along and messing with what we build, you can grab the TangleJS repo on Github)

Anatomy of a Game Loop

A basic game loop

A basic game loop. Image by LazyEyeOzzy, retrieved from Wikimedia Commons

Almost every type game you'll ever play has some form of game loop at its core; most will look quite similar to the above diagram. After any necessary startup (loading resources and such), the game loop takes care of a few basic things:

  1. Handle player input
  2. Update the state of the game and any objects
  3. Render the game state back to the user

Each of these steps break down into sub-steps: handling player input implies collecting it and processing it. Updating game state may include things like running enemy AIs, calculating new positions for moving elements, and collision detection. And user output may include graphics, sounds, or even haptic feedback (like vibration).

The traditional way to achieve these types of loops in JavaScript is via the setInterval method:

Game.fps = 50;

Game.run = function() {
  Game.update();
  Game.draw();
};

// Start the game loop
Game._intervalId = setInterval(Game.run, 1000 / Game.fps);

(Example taken from nokarma.org)

This works pretty well, and many people have used it to great effect. Recently, though, a few of the browser makers have decided to give us a new and improved API called requestAnimationFrame (You can tell it's still pretty new, because the browser vendors still have their own proprietary-named versions: mozRequestAnimationFrame, webkitRequestAnimationFrame, etc). Its purpose is to streamline the management of in-browser animations, since the browser can internally optimize things like repaint cycles that aren't visible from the JavaScript layer. Plus, if your browser tab is hidden, the browser can effectively pause your animation for you, leading to better performance, memory usage, and so on.

Sounds good, right? Here's how we might change our loop to use this new API instead of setInterval:

Game.run = function() {
  Game.update();
  Game.draw();
};

function animate() {
  Game.run();
  requestAnimationFrame( animate );
}

// Start the game loop
animate();

I have a couple of thoughts when I see a game loop like this. One is that it violates the DRY principle, because you have to have this weird animate() function, whose sole purpose is to recursively call itself via requestAnimationFrame, then call Game.run(). Ick.

The second thing I notice is that there's no way to specify frames per second anymore, like there was in the first example. The main reason for this is that requestAnimationFrame is optimized by the browser, so the rate at which it gets called depends on processor speed, the amount of system resources available, and whether the tab is active. For the rendering portion of our game loop, that's just fine — there's no point in burning up your processor drawing to a tab that's not even visible. But what about the update portion of the loop? Should it be bound to the speed at which things are being drawn to the screen? Logic (and indie game developer Chandler Prall) would say no. So, let's try again:

Game.fps = 50;

function render() {
  Game.draw();
  requestAnimationFrame( render );
}

// Start the game's render & update loops
render();
Game._intervalId = setInterval(Game.update, 1000 / Game.fps);

That seems better. Now the draw code can leverage the browser's optimization path via requestAnimationFrame, and the update code can run at our specified rate. If you wanted to get a little more advanced, you could probably try and offload your update loop to a Web Worker, but that's well beyond the scope of this article.

There are a couple of things that this last version of the code doesn't address, which I often find myself wanting in my JavaScript game projects: the ability to dynamically show a realtime FPS count, and the ability to pause and resume the game. Both can be pretty easily accommodated with a simple helper class to abstract this basic level of game management, so I've added one to Tangle, which I'm calling Tangle Core. Here's the meaty bit (the real thing is wrapped in an AMD module, but this gives you the gist):

var tangleCore = {
  init: function game_init(updateFunc, renderFunc, fpsFunc) {
    _paused = true;

    if (fpsFunc) {
      if (typeof fpsFunc == "function") {
        _fpsCallback = fpsFunc;
      } else {
        console.error("[Tangle.main] >> Provided argument fpsFunc is not a function.");
      }
    }

    if (updateFunc && typeof updateFunc == "function") {
      _updateLoop = updateFunc;
    } else {
      _updateLoop = null;
      console.error("[Tangle.main] >> Provided argument updateFunc is null or not a function.");
    }

    if (renderFunc && typeof renderFunc == "function") {
      _renderLoop = function() {
        _checkFPS();  // calls fpsFunc with the latest calculated FPS
        renderFunc();
        _renderLoopId = requestAnimationFrame(arguments.callee);
      }
    } else {
      _renderLoop = null;
      console.error("[Tangle.main] >> Provided argument renderFunc is null or not a function.");
    }
  },

  isPaused: function isPaused() {
    return (_paused == true);
  },

  pause: function pauseMain() {
    if (!_paused) {
      _paused = true;
      clearTimeout(_updateLoopId);
      cancelAnimationFrame(_renderLoopId);
    }
  },

  play: function playMain() {
    if (_paused) {
      _paused = false;
      _updateLoopId = setInterval(_updateLoop, 1000 / 60);  // aim for 60 FPS
      _renderLoopId = requestAnimationFrame(_renderLoop);
    }
  }
};

// to use:
tangleCore.init(Game.update, Game.draw);
tangleCore.play();

Now we're starting to get somewhere! Less boilerplate code in our games == WIN.

Rubber, Meet Road

As with the last post, I've created a simple demo that shows off this new functionality.

As with AssetCache, Tangle Core should be usable in all modern browsers, plus Internet Explorer 8. Once we dive into the specifics of Canvas this may not be the case, but the basic components we've been building so far have applicability in other contexts beyond Canvas-based games. The AMD approach allows us the flexibility to cherry-pick the parts of Tangle we want to use without locking us into a particular programming paradigm.

Next time we'll talk about Screens, States, and how to avoid making your game loops look like a plate of spaghetti.

Resources

Introducing Haiku

Monday, November 12, 2012

Japanese kanji for 'haiku'

I've been pretty busy creating new stuff lately, and last week, I created a little something as a part of my Atto microlibrary to simplify DOM node creation for my widgets (I've experimented with a few templating languages like Mustache and Handlebars, and frankly, while these both works fine for specific implementations, I'd prefer to avoid making my project as a whole less general-purpose by introducing any external dependencies). Anyway, my solution was to code up a small module with a microtemplate specification very loosely based on CSS selector formatting: the intent was to make it compact, but easily grokable once you've learned the rules. As I was largely inspired by the Zen Coding project, I wanted a name that similarly evoked Eastern philosophy, so I called it Tao, and committed it to Github.

After using it for a few days, I decided I liked it so much I wanted it to be its own thing, independent of Atto. So I cleaned it up a bit, sugared in simple attribute substitution a la Douglas Crockford's Supplant, and Haiku was born!

A Simple Example

Probably the easiest way to explain what Haiku does is to compare it to other ways of doing the same thing. When I originally wrote Atto's new Tree widget, my “Vanilla JavaScript” version of the addNode method contained some code that created and manipulated a few DOM elements for the new tree node's label text and expando link:

  // create the expando
  var expando = document.createElement('a'); 
  expando.className = "aw-expando"; 
  expando.href = "#";
  expando.appendChild(document.createTextNode(" ")); 
  srcNode.appendChild(expando);

  // create the label
  var label = document.createElement('span'); 
  label.className = 'label'; 
  label.appendChild(document.createTextNode(srcNode.title || "Unnamed Node")); 
  srcNode.appendChild(label);

Not the ugliest code in the world, but it's a little more cluttered than I wanted. With Haiku it gets cleaner:

  // create the expando and label
  srcNode.appendChild( haiku.create("a.aw-expando[href=#]{ }") );
  srcNode.appendChild( haiku.create("span.label{$title;}",
                       {"title": srcNode.title || "Unnamed Node"}) );

Tidy. Just like in CSS, the period operator (.) indicates a class name, hash (#) specifies an element ID, and square braces ([ ]) are used to specify any other attributes. Curly brackets ({ }) are for text content, and a slightly-modified version of HTML named entity format ($…;) is used for parameter substitution from an object passed to create()'s optional second argument. That's pretty much all you need to know to handle single-element creation.

A More Complicated Example

Say you're fetching a data object containing a list of person objects from a RESTful address book web service:

[
  {
    "name": "Reed Richards",
    "id": 1,
    "address": "Four Freedoms Plaza",
    "city": "New York City",
    "state": "NY"
  },
  {
    "name": "Peter Parker",
    "id": 17,
    "address": "Forest Hills, Queens",
    "city": "New York City",
    "state": "NY"
  }
]

One possible “Vanilla” approach to using this data would be to create a custom generator function that accepts a person object and returns a new DOM node with its contents:

function createPerson(obj) {
// takes a person object and returns a 
representation var item, link; item = document.createElement('div'); item.className = 'person'; item.id = 'contact-' + obj.id; link = document.createElement('a'); link.href = 'http://ppl.net?id=' + obj.id; link.className = 'external'; link.innerText = obj.name item.appendChild(link); item.appendChild(document.createTextNode(" (" + obj.city + ", " + obj.state + ")")); return item; } // loop through the results and add to myFrag people.forEach(function(person) { myFrag.appendChild(createPerson(person)); });

That's a perfectly valid approach to the problem, but it's a bit messy. Templating solutions like Handlebars make things a little cleaner:

// set up the template
var html = "
\ {{name}} ({{city}}, {{state}})\
"; var template_func = Handlebars.compile(html); // loop through the results and add to myFrag people.forEach(function(person) { myFrag.appendChild( template_func(person) ); });

That's better. It seems cleaner to me, anyway. But at least as of today, I don't know of any templating languages that can capitalize on the last few years' worth of performance improvements with the browsers' native DOM creation methods. Maybe that's not a dealbreaker, especially if you precompile your templates like Handlebars and others let you do. Regardless, Haiku is always using the browser-native methods under the hood, so you can rely on good performance in all but the oldest browsers (where it should still work just fine, provided I've done my job properly).

Setting aside the question of performance optimization, I still think I prefer the Haiku solution in this case:

// define the template
var template = "div.person#contact-$id;>\
a[href=http://ppl.net?id=$id;]>{$name;}<{ ($city;, $state;)}";

// loop through the results and add to myFrag
people.forEach(function(person) {
    myFrag.appendChild( haiku.create(template, person) );
});

This snippet introduces Haiku's second type of operators, those used to define relationships between nodes. As in CSS, greater-than (>) indicates a parent-child relationship between two DOM nodes (as is the case with the div and a tags here). Also following CSS conventions, a plus (+) indicates that the two adjacent elements should be siblings of a common parent. The third relationship operator is a logical extension of these two: less-than (<) directs the parser to move up a level in the DOM tree (as with the "(city, state)" text node above), adding the following element to the preceding element's grandparent. (this might be a bit confusing at first, but remember that adding the new node to the previous node's parent would actually make the two nodes siblings, which is what + is for).

Finally, a Counterexample

Haiku isn't the answer in every case, nor do I intend it to be. The compactness of the format that is so appealing in the simple case becomes a hindrance to clarity when the desired DOM tree is too complicated. For example, take this snippet from Jed Schmidt's DOM builder, domo:

dom = HTML({lang: "en"},
  HEAD(
    TITLE("domo"),
    STYLE({type: "text/css"},
      CSS("#container", {backgroundColor: "#eee"})
    )
  ),

  BODY(
    DIV({id: "container"},
      "For more details about domo, see the source: ",
      A({href: "//github.com/jed/domo/blob/master/domo.js"}, "View source")
    )
  )
)

First of all, Haiku doesn't support the insertion of CSS content since it's based on CSS selector format (you'd somehow have to either escape everything, making it uglier, or you'd need to hide it in your parameters object for insertion via template expansion), so domo's already ahead there.

Secondly, you'd have to break the Haiku template up into multiple lines like we did with the Handlebars template earlier, but it wouldn't be as nicely-formatted:

var params = {"cssContent": "#container {backgroundColor: \"#eee\"}"};
var dom = haiku.create("html[lang=en]>\
head>title{domo}+style[type=text/css]{$cssContent;}<\
body>div#container>{For more details about Haiku, see the source: }+\
a[href=//github.com/jed/domo/blob/master/domo.js]>{View source}", params);

Yuck. That works, but it definitly doesn't leave me with the same happy feeling I got with the Atto Tree rewrite.

UPDATE: Actually, I just tested this and verified my hunch that it won't work with the current version of Haiku, since parameter substitution happens before the template expression gets parsed. That means the intended CSS content still ends up getting parsed as if it were part of the node tree expression.

Bottom line: right tool, right job.

What's Next?

The idea of using Haiku server-side in a Node.js context appeals to me, but it's not currently CommonJS-compatible, so that's not possible just yet (although I'm considering working on this).

I've also thought about going deeper into the Zen Coding toolbox, for features like abbreviation groups (like body>(header>h1)+(div#main)+(footer>span)), element multiplication (li*5>a), or item numbering (Zen Coding's use for the $ operator, which I'm using in a different way: li#item$*3).

These gaps aside, if you're looking for a lightweight DOM builder to give your code a little more zen, give Haiku a try.

Haiku makes DOM trees
so simple to generate,
I think you'll like it.


UPDATE: After I published this post, a couple of friends pointed out to me how similar in spirit Haiku is to Kris Zyp's put-selector project. Honestly, although I briefly looked at that project last summer as part of my evaluation of Kris's then-in-beta dGrid, I'd since forgotten it even existed, mostly because I haven't worked much with Dojo in the past 9 months. (That said, Kris's project has some very cool features that have given me some ideas for future enhancements to my own!) So although I can't definitively say that I wasn't subconsciously inspired by put-selector when I wrote Haiku, it certainly wasn't a deliberate duplication. Rather, I take it as an example of convergent evolution at work.

JavaScript 101: Hoisting

Wednesday, November 7, 2012

The other day I was in a conversation that revolved around some of JavaScript's more interesting features, and the subject of hoisting came up. It occurred to me that even though I understand the basic concept of hoisting, I was at a loss about how to succinctly explain it.

Now, as someone who has been working on the Web for years and years, I'm a little embarrassed by that. So, I'm going to use my embarrassment as a way to break through my blogger's block: this post is the first of what I hope will be a series of related articles explaining tricky JavaScript concepts in simple terms. I'm going to be a little unoriginal and call it JavaScript 101. While primarily a writing exercise on my part, hopefully it might prove useful to others. So here we go!

Declaration vs Assignment

The key to understanding hoisting is knowing the difference between identifier declaration and assignment. Just like it sounds, declaration is when your code “declares” that a variable exists within your current scope. The JavaScript interpreter running your code will always take these declarations and "hoist" them to the beginning of their containing scope (remembering that functions are the only scope containers in JavaScript). The assignment of that variable's value, however, remains in whatever place you wrote it. Consider the following code:

function foo() {
  if (a == 1) {
    b = 2;
  } else {
    b = 3;
  }
  var a = 1;
  return a + b;
}

Would it surprise you to know that this is a perfectly valid JavaScript function, even though it apparently tests the value of `a` before even declaring it? Further, would it surprise you to know that the function's output is `4`? The reason why has to do with how the JavaScript interpreter re-arranges the code before evaluating it:

function foo() {
  var a,b;  // a and b are both undefined
  if (a == 1) {
    b = 2;
  } else {
    b = 3;
  }
  a = 1;
  return a + b;  // 1 + 3 == 4
}

As I said before, the declaration of the `a` variable gets hoisted up to the top of the scope, but its assignment stays put, so when the if (a == 1) condition is evaluated, the value of `a` is `undefined`. That causes the code to execute the `else` branch, setting the previously-declared (invisibly declared, in this case, but that's a subject for another post) `b` variable to the value `3`. Then, `a` gets its assignment to `1`, and the function returns 1+3, or 4.

Clear as mud?

Function hoisting

Another interesting wrinkle to hoisting is the difference between these two ways of defining functions:

function myFunc() {
  function foo() { alert('Hello world'); }
  var bar = function() { alert('Hello world'); }
}

Both lines create a simple function that just shows an alert, right? Sure, but they go about it differently. The first is a function declaration, and the second is a function expression, and your browser treats them differently. Remember, declarations get hoisted, but variable assignments don't, and that's essentially what `bar` is in this case: a variable whose declaration gets hoisted to the top of the scope, but whose value, in this case an anonymous function expression, gets assigned later on:

var bar;  // undefined
function foo() { alert('Hello world'); }  // evaluated right away
bar = function() { alert('Hello world'); }  // the variable bar gets set to an anonymous function

So, the lesson to take from this one is if you want to have code that calls functions before they appear in your code, be sure to use function declaration syntax. Otherwise, you'll get weird errors and not know why:

function myFunc() {
  foo();  // outputs "Hello world"
  bar();  // TypeError: undefined is not a function
  function foo() { alert('Hello world'); }  // evaluated right away
  bar = function() { alert('Goodbye'); }    // declaration is hoisted, assignment deferred until here
}

Further reading

I only scratched the surface here, and didn't really go into excessive detail about why JavaScript behaves this way. If you want more details, Ben Cherry's post is a great starting point. I also really liked Elegant Code's treatment of function hoisting.

js13kGames: On Polish

Tuesday, September 11, 2012

In my last post, I said that I had the basic tile mechanics (swapping, sliding, and group matching) in place for my js13kGames entry, Blak & Bloo. At the time, I felt like the next thing I needed to tackle was polish:

To have a satisfying experience, though, requires more polish... it's going to require custom tile graphics, animations, and tweening of tile movements. So next, I'm going to need to write a Sprite class.

Me, last time

So with this in mind, I spent a few hours scouring the Internet for suitable (and usable) fruit & berry images, drawing a custom "picnic basket" style background to replace the plain black frame in the prototype, and modified the codebase to use these images in the render loop. There's a definite difference in the "before" and "after" screenshots of this change:

Blak & Bloo gameboard with basic, colored-box tiles
BEFORE

This colored-boxes version kind of looks like one of those optical illusions, doesn't it?

Blak & Bloo with improved, image-based tiles
AFTER

Overall, I'm pretty happy with the direction the art's going, although I'll want to tweak it somewhat as we go along, so it doesn't get too "busy".

Once I'd made these changes, I decided to check the js13kGames contest's Facebook page and saw that several entries had already been posted. I went over to check out what kinds of things other people were doing, and was blown away by the diversity and quality on display!

Holy Miyamoto, I've got to step up!

Hitting the 13KB Wall

Unfortunately, I got trapped in a mental cul-de-sac of sorts — I really want the polish that comes with the better graphics, but they made the payload much bigger than the contest's 13-kilobyte limit!

I tried a few things to shrink my footprint, with varying degrees of success:

  1. I base64-encoded the images as data URIs, hard coded at the head of my JavaScript code... no size savings there, because I'm using PNG images, which are already pretty efficiently stored
  2. I opened up my images in The GIMP again, and meticulously removed all the extraneous fields of color I could, if they could conceivably be drawn in by canvas fillRect() calls at runtime. This helped a bit, but not nearly enough to get my under the size limit.
  3. Finally, I realized what should have been an obvious avenue for size-reduction: I dropped the color depth of the images from 24-bit (RGB / true color) to 8-bit (limited to an optimized 256-color palette). This last avenue proved to be the most fruitful: I'm now back under the 13kb limit, with room to spare.

Along the same lines, I'm beginning to realize that my reliance on my minimal game framework, TangleJS, is making things bigger than they need to be. Case in point: the state machine code. But that deserves an entire blog post, so I'll save that for next time, probably in the post-mortem.

Two days to go!

js13kGames: Library Design and Core Mechanics

Friday, August 31, 2012

js13kGames logo Last week I started working on a game for the js13kGames competition, to see if I could do something fun and cool with open web technologies in less than 13 kilobytes. It's been an interesting week, I've learned a couple of things about my workflow, and I've almost got something playable to show off (maybe next week).

Need-Driven Library Design

The first thing I've run into is how incomplete my in-development HTML5 game library, TangleJS, still is. I've made a couple of decent games from scratch in the past, and started abstracting ideas and lessons learned there to make a better, more deliberate platform for my future efforts. I'm chronicling that process in my blog series, Let's Make a Canvas Library. The mistake I made was in thinking that it was in any way ready for me to start actually, you know, using.

The game I'm building for js13kGames, Blak & Bloo, is my first real effort to build something using the barely-just-enough-library-and-no-more philosophy that's driving Tangle's development. At every step, when I found some new feature I needed (e.g. sprite animations, state machine transition notifications, etc), rather than just grabbing something that worked in a previous game and hacking it down to fit my immediate need, I've tried to take a step back and deliberately design something more general-purpose that can be easily reused as part of the overall Tangle library. It's... well, it's slowed me down during what should have been a quick week of prototyping.

That said, I believe the extra effort I've spent doing this hasn't been wasted; on the contrary, Tangle won't ever be really useful to me unless I extend it organically by growing it on demand in this way. It's just made progress slower and less interesting than I would've liked it to be. Thus, I haven't really had much to blog about. At least, not until yesterday.

Game Mechanics

As a reminder, my vision for Blak & Bloo is a 2-player, cooperative/competitive Match-3 puzzle game. As in all games of this style, the goal will be to line up groups of 3 or more matching tiles (in this case fruits and berries) to score points. The “hook” I alluded to last time, the thing that I hope will make the game fun to play, is that Player 1 and Player 2 have totally different ways of interacting with the game... to make tile matches, Player 1 can only swap adjacent tiles, and Player 2 can only shift rows and columns along their axes:

tile-swapping vs tile column shifting

So far, I've got the code written to make these swaps and shifts (and any resulting group matching) happen instantly, and the tiles are rendering themselves as simple swatches of color, like in the image above. To have a satisfying experience, though, requires more polish... it's going to require custom tile graphics, animations, and tweening of tile movements. So next, I'm going to need to write a Sprite class.

js13kGames: Kickoff

Sunday, August 19, 2012

js13kGames logo This past Monday marked the beginning of a cool new 1-month competition called js13kGames, where the aim is to use open web technologies (i.e. JavaScript, HTML5, and CSS3 — no plugins) to build an online game. I've had a couple of ideas simmering on the back burners of my brain for the past few months, as I've been working on my Let's Make a Canvas Library blog series, and I've decided to take this contest as an opportunity to grab one of those ideas and front-burner it for the next 4 weeks. Should be a fun exercise, and when the month's over, I hope to have something neat to show for it.

Design Brainstorming

So the original kernel of my idea was to make a simple puzzle game in the Match-3 vein, something like Bejewelled maybe, but to somehow change the dynamic. The trick is, the genre is pretty crowded with innovations, so it's a little hard to come up with something that's never been done before. A less-than-innovative game could be saved with awesome artwork or music, but sadly, my artistic skills aren't quite at the level where they could redeem an otherwise-boring game, so that's not really an option.

About the same time I started trying to think of clever Match-3 game hooks, I needed to create some fake game assets for my AssetCache demo page. I hit upon the fake game name "Black & Baloo" for a title screen, and kinda liked it:

Blak & Bloo title screen prototype

The name started out as just a simple play on words, sparked by something in my gray matter about a bear named Baloo in an old favorite story, and was never intended to be any more than a throwaway for that TangleJS tutorial page. But the more I thought about it, the more I realized I could use it as the hook I was needing!

What if, I thought, I based my game around the interactions of two player characters, named Black and Baloo respectively? (I've since decided to change the names to Blak and Bloo, since the pun still works that way, and it's a little more unique). The idea of collaborative / competitive Match-3 hasn't been explored very well, I don't think, so there's a novelty factor. Plus, the two-player mechanic provides some interesting technical challenges for me to overcome, which I'll probably talk about soon.

Once I'd hit upon this core idea, my ideas began to take shape. Next time, I'll talk about another one of the game mechanics I'll be playing with to make the game (and the development process) more interesting. It's gonna be a fun month!

Let's Make a Canvas Library: Assets

Monday, July 16, 2012

Welcome back to Let's Make a Canvas Library, our tutorial series focused on the principles of building a good personal code library for writing games and other cool stuff with HTML5 Canvas. Today we're going to focus on assets: images and sounds.

Like the blog series it's modeled on, my aim is primarily educational, not to come up with an awesome library that every person on the planet is going to want to use. That said, I'll be committing each improvement to a new Github repo I'm calling Tangle, for anyone who wants to follow along.

Asset Management

preloading splash message

Unless you're really embracing your retro muse, just about any game you set out to build is going to have assets: the images and sounds that give it its unique flavor. For many games, these assets will take a while to load, especially over low-bandwidth connections like those usually found on mobile devices. That being the case, you're going to want to preload those files before starting the main game loop. And since this is something you're going to do over and over (and over) again, on basically every game you build, it makes sense to make it a part of your library.

In my first few games, my preloading routine was limited to just images and javascript modules (when I needed sounds, I did those separately, using SoundManager2 or something similar). For a while, my preload process had two phases: first, I'd pass a list of images and modules to the Preloader class, which would then call dojo.require() on the modules, and pass the list of images along to a global ImageCache object to preload separately. When all the code and images were loaded by the Dojo loader and ImageCache, then the Preloader class would signal completion back to the calling routine. In retrospect, it probably involved a few too many steps of indirection:

//
// (in main.js)
//
dojo.addOnLoad(function init_loader(){
    dojo.require("loc.Preloader");
    dojo.addOnLoad(preload);  // when loc.Preloader is loaded, run preload()
}); // end of init_loader()

function preload() {
    window.loader = new loc.Preloader({
      images: {
        title: "res/title.png",
        map:   "res/map.png",
        floor: "res/floor.png",
        tiles: "res/underworld_tiles.png",
        items: "res/items.png",
        link:  "res/link.png"
      },
      modules: ["id.MapQuest"]
    })

    if (loader.ready()) {
        // if everything was cached (or we're on a really fast network),
        // then we're ready to proceed.
        init_game();
        delete window.loader;
    } else {
        // still waiting for things to preload; listen for onReady
        var listener = dojo.subscribe("loc.Preloader.onReady", function() {
            dojo.unsubscribe(listener);
            init_game();
            delete window.loader;
        });
    }
} // end of preload()

function init_game() {
    window.game = new id.MapQuest({
        ...
    });
}

// ------------------------------------------------
// (in Preloader.js)
//
dojo.provide("loc.Preloader");
dojo.require("loc.ImageCache");
dojo.addOnLoad(function() {
    if (!window.imageCache) { window.imageCache = new loc.ImageCache(); }
});

dojo.declare("loc.Preloader", null, {
    images: {},
    modules: [],
    _isReady: false,
    constructor: function preloader_constructor(args){
        dojo.mixin(this, args);

        for (var i in this.images) {
            // treat item as a key:value pair
            window.imageCache.addImage( i, this.images[i] );
        }
        for (i in this.modules) {
            // load each requested item and then register an OnLoad handler
            //   to be notified when they're all done
            dojo.require(this.modules[i]);
        }
        dojo.addOnLoad(function() {
            if (window.imageCache.ready()) {
                dojo.publish("loc.Preloader.onReady",[]);
            } else {
                this.listener = dojo.subscribe(
                    "loc.ImageCache.onReady",
                    function() {
                        dojo.unsubscribe(this.listener);
                        delete this.listener;
                        this._isReady = true;
                        dojo.publish("loc.Preloader.onReady",[]);
                    }
                );
            }
        });
    },
    ready: function preloader_ready() {
        return this._isReady;
    }
});

// ------------------------------------------------
// (in ImageCache.js)
//
dojo.provide("loc.ImageCache");
dojo.declare("loc.ImageCache", null, {
    constructor: function ImageCache_constructor(args) {
        this._sprites = {};
        this._loadStatus = {};
    },
    addImage: function addImage(name,src) {
        if (name in this._sprites) {
            return;
        } else {
            this._sprites[name] = new Image();
            this._loadStatus[name] = false;
            this._sprites[name].src = src;
            this._sprites[name].onload = dojo.hitch(this, function() {
                this._loadStatus[name] = true;
                if (this.ready()) {
                    dojo.publish("loc.ImageCache.onReady",[]);
                }
            });
        }
    },
    hasImage: function hasImage(name) { return (name in this._sprites); },
    getImage: function getImage(name) {
        if (name in this._sprites) {
            return this._sprites[name];
        } else {
            console.error("Image name '", name, "' not found");
            return null;
        }
    },
    ready: function ready() {
        var retVal = true;
        for (var id in this._sprites) {
            if (id in this._loadStatus) {
                retVal &= this._loadStatus[id];
            } else {
                return false;
            }
        }
        return retVal;
    }
});

Making it Better

While this approach works, there are several ways we can go about improving it:

  1. If you read my previous post, you know that crafting our modules in an AMD-compatible format takes care of code preloading, so that's one less thing we need our Preloader to do.
  2. Notice that both Preloader and ImageCache have an onReady event (implemented using Dojo's publish/subscribe methods). That's a clue that we can probably collapse their functionality into a single class.
  3. While we're making changes, and given the broad browser support for the HTML5 <audio> tag, it's probably worth broadening our cache support from just images to include audio assets as well (ultimately we may want to include other types of media like video or fonts too, but that's not necessary just yet).

Bearing these ideas in mind, here's what a new, streamlined, asset-agnostic, AMD-compatible Preloader might look like (note that I've omitted a few details for the sake of brevity; you can review the whole thing over on GitHub):

define(
    ['atto/core','atto/event'],
    function(atto,CustomEvent) {
        function constructor(args) {
            var _assets     = {},
                _loadStatus = {},
                _events = {
                    error:  new CustomEvent('tangle.assetCache.error'),
                    ready:  new CustomEvent('tangle.assetCache.ready'),
                    loaded: new CustomEvent('tangle.assetCache.loaded'),
                },
                _types = {
                    IMAGE: 1,
                    AUDIO: 2
                },
                _extension_to_type = {
                    png: 1, bmp: 1,  gif: 1, jpg: 1, jpeg: 1,
                    wav: 2, webm: 2, ogg: 2, mp3: 2, aac: 2
                };

            function _assetTypeFromFilename(fileName) { ... }

            function _createLoadCallback(assetName) { ... }

            function _createErrorCallback(assetName) { ... }

            function _addAsset(name, src) {
                if (name in _assets) {
                    _events.error.dispatch({name:name,
                      details:"Asset '"+name+"' is already in the cache"});
                    return;
                } else {
                    var assetType = _assetTypeFromFilename(src);
                    switch (assetType) {
                        case _types.IMAGE:
                            _assets[name] = new Image();
                            atto.addEvent(_assets[name], 'load',
                              _createLoadCallback(name), false);
                            atto.addEvent(_assets[name], 'error',
                              _createErrorCallback(name), false);
                            break;

                        case _types.AUDIO:
                            _assets[name] = new Audio();
                            atto.addEvent(_assets[name], 'canplaythrough',
                              _createLoadCallback(name), false);
                            atto.addEvent(_assets[name], 'error',
                              _createErrorCallback(name), false);
                            break;

                        default:
                            // unsupported asset type
                            _events.error.dispatch({name:name,
                              details:"Asset type '"+assetType+"' not supported."});
                            return false;
                            break;
                    }

                    _loadStatus[name] = false;
                    _assets[name].src = src;
                }
            }

            function _hasAsset(name) { ... }
            function _getAsset(name) { ... }
            function _getAssetType(name) { ... }

            function _ready() {
                var retVal = true;
                for (var id in _assets) {
                    if (id in _loadStatus) {
                        retVal &= _loadStatus[id];
                    } else {
                        return false;
                    }
                }
                return retVal;
            }

            return {
                TYPES        : _types,
                addAsset     : _addAsset,
                hasAsset     : _hasAsset,
                getAsset     : _getAsset,
                getAssetType : _getAssetType,
                ready        : _ready,
                events       : _events
            } // end of public interface
        } // end of constructor

        return constructor;
    } // end AMD callback function
);

Let's take a look at a few of the more interesting pieces here.

AMD Wrapper

define(
    ['atto/core','atto/event'],
    function(atto,CustomEvent) {
        function constructor(args) {

            ...

            return {
                TYPES        : _types,
                addAsset     : _addAsset,
                hasAsset     : _hasAsset,
                getAsset     : _getAsset,
                getAssetType : _getAssetType,
                ready        : _ready,
                events       : _events
            } // end of public interface
        } // end of constructor

        return constructor;
    } // end AMD callback function
);

We've seen this before, it's the same basic AMD-flavored version of the Revealing Module pattern that I showed off in the previous post in this series. As in that case, I'm using AMD's define method to specify my module's dependencies, here a couple of modules from my minimal JavaScript library Atto, and return a factory function that can be used by downstream code to create an instance of my class. So far, so good.

Communicating Events

_events = {
    error:  new CustomEvent('tangle.assetCache.error'),
    ready:  new CustomEvent('tangle.assetCache.ready'),
    loaded: new CustomEvent('tangle.assetCache.loaded'),
}
...
_events.error.dispatch({name:name, details:"Asset '"+name+"' is already in the cache"});
_events.ready.dispatch({});

This is new, but not really worth going into too much detail about here. You can think of Atto's Event class as a slightly more robust implementation of the basic pub/sub pattern, but using object literals instead of strings for the topics. As the browser progresses through the preload process, AssetCache dispatches events that can be watched by the main game code to show a loading progress bar, display a status message, or to know when the assets are available to be used:

var progressBar = new ProgressBar({min: 0, max: assetCount});

cache.events.error.watch(function(data) {
   _log(data.details);
});

cache.events.loaded.watch(function(data) {
   _log('Loaded asset ' + data.name + '.');
   progressBar.setValue(progressBar.getValue() + 1);
});

cache.events.ready.watch(function(data) {
   _log('All assets loaded.');
   progressBar.setValue(progressBar.getMax());
   game.setState(game.states.TITLE);
});

Determining Load Status

That leads us to AssetCache's bread and butter, the code that actually does the asset preloading:

function _createLoadCallback(assetName) {
    return function() {
        _loadStatus[assetName] = true;
        _events.loaded.dispatch({name:assetName});
        if (_ready()) _events.ready.dispatch({});
    }
}
function _createErrorCallback(assetName) {
    return function() {
        _loadStatus[assetName] = false;
        _events.error.dispatch({name:assetName,
            details:"Asset '"+assetType+"' failed to load."});
    }
}
...
var assetType = _assetTypeFromFilename(src);
switch (assetType) {
    case _types.IMAGE:
        // image: this is by far the simple case
        _assets[name] = new Image();
        atto.addEvent(_assets[name], 'load', _createLoadCallback(name));
        atto.addEvent(_assets[name], 'error', _createErrorCallback(name));
        break;

    case _types.AUDIO:
        // audio; this will take a little more magic, due to browser codec issues
        _assets[name] = new Audio();
        atto.addEvent(_assets[name], 'canplaythrough', _createLoadCallback(name));
        atto.addEvent(_assets[name], 'error', _createErrorCallback(name));
        break;

    default:
        // unsupported asset type
        _events.error.dispatch({name:name,
            details:"Asset type '"+assetType+"' not supported."});
        return false;
        break;
}
_loadStatus[name] = false;
_assets[name].src = src;

We have some very basic code to determine file type based on its extension, then create the appropriate DOM element, Image or Audio (we should probably wrap the Audio case in a try/catch block, since we're trying to retain as much cross-browser compatibility as possible, and not all browsers support the Audio tag). Then, we attach a couple of event handlers to the element to keep track of its loading progress, and assign its src attribute to the appropriate URL to initiate the load. The Image element has pretty straightforward load and error events, but Audio, in contrast, doesn't fire a load event when it's finished loading. Instead, you get the canplaythrough event, which fires when the browser decides it has buffered enough data from the file so that if you start playing immediately, it will have the whole thing soon enough to play without stuttering. That's close enough for our purposes.

Audio Support Still Stinks

One note on preloding audio assets: AssetCache's support for audio files will depend on your browser and operating system. On my Windows 7 laptop, Google Chrome (v20) can load and play back both the mp3 and ogg audio files, but Firefox (v13) only supports the ogg file, and IE9 only supports the mp3! Neither audio file is loadable on my locked-down work computer, where I'm stuck with IE8, and I couldn't get either one to load on my stock Android 2.3 browser either. I haven't delved any deeper into the mobile issue, but I suspect that the audio object may have actually loaded, but not fired the canplaythrough event. Or maybe it couldn't load either format, I'm not entirely sure.

We'll revisit this crazy audio situation in a later tutorial to find a better cross-browser solution. You'd think that this would be an ideal use case for a library: it would be so much nicer if your app code could just specify a single, named audio asset, and let the library figure out the right file format to load based on browser and platform capabilities. In theory, the audio element exposes a method that reports on your browser's ability to play various file types, but it's notoriously vague and generally unhelpful, so relying on it to determine a caching strategy may not be very helpful.

Demo Time!

I've set up a simple demo page that shows off AssetCache's basic functionality, albeit not yet in the context of an actual game.

AssetCache should work in all modern browsers, and as I said, it even has limited support for Internet Explorer 8. Even though Tangle is just a reference implementation and not a truly production-ready library, as a general principle I try to build things that are as broadly usable as possible, so in theory parts of Tangle could be used to build a game that gracefully degrades on older, less-capable browsers. After all, the whole principle of modular dependency loading that AMD enables means that if you want to cherry-pick certain pieces that you find useful and not use the rest of the library, you're free to do so.

Next time we'll cover the basics of building a game loop, and actually use AssetCache to build something interesting.

Resources

Let's Make a Canvas Library: Modules

Wednesday, July 4, 2012

Hello and welcome to part 1 of Let's Make a Canvas Library, a tutorial series focused on the principles of building a good personal library for working with HTML Canvas.

But first, an apology: I originally announced this blog series immediately after my presentation at UtahJS on the same subject, and promised that part 1 would be going online that Friday. Obviously, it didn't.

So, what happened? I fell in love:

What's so great about AMD?

AMD, officially known as the Asynchronous Module Definition API, has been gaining steam in recent months as a solution for several longstanding issues in the JavaScript world: non-blocking script loading, dependency management, standardized module definition syntax, and global namespace abuse. The Dojo toolkit, which I've been using for the past few years, had a fairly elegant approach to modules that addresses a lot of these concerns, and it's one that I've put to good use in my personal game-development library. However, over the past year Dojo has been moving away from that format and migrating their codebase over to AMD-style modules, which are quickly becoming the de facto standard for client-side JavaScript libraries* (jQuery, MooTools, and Firebug have all built in AMD support recently). While similar in spirit, the AMD API is different enough that I was unwilling to take the time to figure it out and convert my old code, until a recent project at work gave me the opportunity to build something new from scratch.

In short, I'm an AMD convert. Everything that felt hacky to me about JavaScript before, from documenting a module's dependencies in its header comments, to including a pile of link and script tags in my HTML pages in the exact right order to ensure proper dependency preloading, has a solution in the AMD approach. Take, for example, the simple TabContainer widget I built as part of my minimal Atto library. Here's what you had to do in your HTML to use the original, non-AMD version:

<link rel="stylesheet" href="/js/atto/awAccordion.css"/>
<script src="/js/atto/aw-core.js"></script>
<script src="/js/atto/awAccordion.js"></script>
<script>
    aw.core.addLoadEvent(function() {
        var myWidget = new aw.Accordion(aw.core.byId("containerNode"), {});
    });
</script>

There are a couple of things about this not to like. First, the widget won't work without the associated CSS syles, so we either have to explicitly link to the appropriate CSS file in the invoking HTML (ugh), or execute a hack of some kind in the JavaScript to guess the correct URL for the CSS file (tricky, since a JavaScript file doesn't know its own URL location when it's being evaluated), and then load it via Ajax.

The second problem with this approach is that awAccordion.js can't stand on its own, as it relies on a window-level object called aw having been created first by its implicit dependency, aw-core.js. This object would serve as container for the new widget's factory class, but also provided necessary helpers (like _loadResource) that simplified the widget's logic and eliminated redundant code paths for pages that included multiple Atto widgets. To be sure, centralizing reusable code is a good thing, but it's pretty nasty that in order to use this (admittedly very barebones) widget, my HTML page has to reference not one, but three separate files (one CSS and two JavaScript), and use an explicit onLoad event to know when everything was actually ready to use.

Compare that to the code needed to use the updated AMD-compatible version of this same widget:

<script src="/js/require.js"></script>
<script>
    require(["atto/core", "atto/accordion"], function(atto, Accordion) {
        var myWidget = new Accordion(atto.byId("containerNode"), {});
    });
</script>

When using an AMD-compatible loader (there are several; RequireJS and curl are two of the most frequently used), you get two global functions: require() and define(). Although there are a few alternative calling syntaxes, require typically takes two arguments: a list of strings representing the resources you need, and a function to execute when those resources (and any of their dependencies) are all loaded, which eliminates the need for an onLoad event. Usually this callback function should define an argument for each module in the required list, so that the loader has a way to give you a reference to it. For example, in the above code, we're requiring two modules, "atto/code" and "atto/accordion", and the callback names these atto and Accordion (although I could have called them "kumquat" and "rutabaga" if I had wanted to, since these are just references).

One important note: outside of this callback, neither atto nor Accordion are defined or available. This keeps the global namespace clean, but may take some getting used to for programmers who are accustomed to having everything available off of the window or document objects.

The second function provided by an AMD-compatible loader is define, and is used, logically enough, to define a module. Here's a simple example of a widget factory class:

// declare the Atto Accordion widget
define(
    ["atto/core","require"], // explicitly declare Atto Core as a dependency
    function(atto) {
        // make sure the appopriate CSS has been loaded for this widget
        var forWidget = "atto-accordion";
        if (!document.querySelector("style[data-for-widget='"+forWidget+"']")) {
            require(["text!atto/accordion.css"], function(rawCss) { atto.addWidgetCss(rawCss, forWidget); });
        }

        function constructor(rootNode, optionArray) {
            // (private variables and function definitions omitted for brevity)

            return {
                root     : _root,
                addPanel : _addPanel
            } // end of public interface
        } // end of constructor

        return constructor;
    } // end function
);

The typical calling signature for define mirrors that of require: a list of strings representing the module's dependencies, and a function that is executed when those dependencies are loaded, which returns the contents of the module (in this case a constructor function for an Accordion widget). The AMD format allows you to explicitly specify a module name as the first argument to define, but current best practice is to omit it, allowing an optimization tool to fill in the name at compile time.

Okay, I get it, AMD's awesome. So what?

So my first topic for Let's Make a Canvas Library was going to be about asset management and preloading, which I had approached previously in a way that was very strongly tied to Dojo's module loader. When I became an AMD convert, I realized this was no longer the best way to solve the problem of preloading. In fact, the need for the Preloader class, which took an arbitrary list of Dojo module names and image paths and preloaded them all, all but disappeared! We'll still need an AssetCache class to handle preloading of images and sounds, but this post is long enough, so we'll save that for next time.


* Yes, I realize that AMD isn't the only option, and that CommonJS has its fans. Personally, though, I feel like AMD is easier to grok than CommonJS, so there you go.

Shorthand parseInt() alternative

Tuesday, June 12, 2012

I'm still working on teasing out asset management in a generic way for the next installment of Let's Make a Canvas Library. Hopefully it'll be ready today or tomorrow. Meanwhile, I just discovered a cool little JavaScript trick via script.aculo.us's creator, Thomas Fuchs.

JavaScript's type coercion, which automatically converts a group of variables to compatible data types before performing operations like concatenation or addition on them, is pretty well known and occasionally affectionately mocked. So when you've got an argument coming into a function that you're pretty sure is a number, but might actually be a string containing a number, the accepted way to make sure you've got an actual number you can do math with is to pass it through parseInt():

function plusOne(n) {
// returns NaN if n is not a number, returns n+1 otherwise
   return isNaN(n) ? NaN : parseInt(n) + 1;
}

Pretty straightforward, yes? So then today I read Thomas's blog entry comparing code written in Prototype.js with a new port of the same class to underscore.js, and in comparing the two code blocks, I noticed that he was using an extra plus operator (+) to coerce a variable to its numeric version:

// prototype (older) version:
function(b,o){ return b + parseInt(o) }

// underscore (newer) version:
function(b,o){ return b + +o }

I confess I'd never seen this method before, so I played around with it a bit in my console to see if it was functionally equivalent to parseInt(); it's not, exactly, but it covers the simple case:

var x = '123', y = '45px', z = 'six';

> console.log(parseInt(x))
123

> console.log(+x)
123

> console.log(parseInt(y))
45

> console.log(+y)
NaN    // interesting...

> console.log(parseInt(z))
NaN

> console.log(+z)
NaN

So, there are two big differences I see: first, parseInt() can handle "dirty" input, i.e. a string that starts with a number but has other non-numeric characters too (like '45px' above), and the prefixed-+ method can't (it just returns NaN). Secondly, parseInt can take an optional radix, so you can convert from, say, octal or hexidecimal. Those two differences mean that this shortcut isn't going to be universally useful, but if you have an execution environment where these limitations are acceptable, go for it.

Let's Make a Canvas Library

Sunday, June 3, 2012

This past Friday I was privileged to speak at the first ever Utah JavaScript conference, UtahJS, in Salt Lake City. My talk centered on the challenges inherent to using HTML5 Canvas to build rich internet games, and advocated the (perhaps radical) notion that instead of using one of the many, many available game frameworks or libraries, aspiring game devs would be better off writing their own:

  • you can be assured that you're not pushing any extra, unnecessary bytes to client devices (especially important on mobile)
  • you have full control over your module's interfaces, so don't have to conform to someone else's coding style
  • you get a better understanding of how things work, which becomes important when you need to debug things that go awry.

The talk was primarily focused on principles, rather than on concrete code examples, although I did have a little time at the end to briefly run through some of the code I'd written for Canvassa, which evolved into Infinite Dungeon, and which I am now porting to Fenjin. I got the sense both from questions and comments during my talk as well as several conversations afterward that people wanted a little more meat. So, let's build something together!

Let's Make a Canvas Library is a new series I'll be writing here on Palagpat Coding. Together, we'll walk through the coding of a simple HTML5 Canvas game, building up our custom game library as we go. Over the coming weeks, I expect to cover the following topics:

  • Preloading & caching game assets (images, sounds, etc)
  • Constructing the game loop
  • Managing sprites
  • Handling interactions between the player, enemies, and stage (i.e. collision detection)
  • Basic physics (and why you probably don't need Box2D)
  • Cross-platform sound
  • Multiple input/control methods

It's likely that this list will change as the game begins to take shape, and some topics will take longer to cover than others. My goal isn't to build something robust and put it on Github for all the world to use; rather, it's to walk you through building something that gets you started with your own library, custom-tailored to the kinds of things you'd want a library to do for you.

You can expect to see the first article in the series this Friday. Until then!

Polyfilling NaCl

Sunday, June 3, 2012

A few months ago I had a crazy idea. In reading about Google's Native Client (NaCL) initiative to bring compiled code onto the web, I've seen arguments both for and against it, each side predicting that the other would bring about the End of the Web As We Know It — at least, that's the way it seemed the conversation was trending.

As a front-end engineer who has spent a lot of time over the past 10 years writing JavaScript, I've grown to love its power, simplicity, and yes, even its quirks. Initially, I admit that I saw NaCl as something of a threat—non-JavaScript programmers trying to take over the Internet, in the same way that native apps dominate the major mobile platforms, even on phones with very capable web browsers. What I'm starting to realize, though, is that it doesn't have to be an either/or situation... Google is just offering us another option, another path to getting cool stuff on the Web. Everybody wins, right?

Well, not so much. As of now, no other browser manufacturer has plans to implement NaCl or its Pepper Plugin API (PPAPI), which exists to bridge native code modules and JavaScript.

Here's the danger I see: NaCl is compelling enough that people are going to want to use it, despite the fact that it locks them into a single browser. We've been here before, with Internet Explorer 6 and ActiveX. In its day, IE6 was an awesome browser to target, and I admit that I wrote plenty of code that leveraged its cool features, without giving much thought to whether things would work on Netscape, Opera, or any other browser. Does everyone remember the old "this site best viewed in IE" disclaimers? Do we really want to repeat that mistake?

So what's the solution? This brings me to my crazy idea: why not polyfill the Pepper Plugin API (PPAPI) for browsers that don't natively support it? With a unified coding surface, front-end developers could write one version of their web app that could leverage Native Client modules on Chrome, and fall back to non-NaCl versions — using, say, Flash, Silverlight, or a Web Workers — on other browsers. Of course, these fallback modules would need to be written and pulled in for all non-NaCl browsers, but these could probably be written in a generic way to promote code sharing and reuse. Then the JavaScript code invoking those modules could stay the same, native or not.

I'm not sure this is really doable, because even with Mozilla's efforts, the likelihood of Microsoft, Apple, and Opera jumping onboard and implementing Mozilla's experimental features sans support from the W3C or WHATWG isn't great. Unless, of course, the demand is there. This may be just the thing Mozilla needs to win back developer hearts and minds from Chrome.

Passing function parameters through settimeout

Thursday, May 31, 2012

Recently I was following an interesting thread on the Utah JavaScript user group's discussion forum. Originally bemoaning the quality gradient between W3Schools and Mozilla's MDN, the original poster cited the example antipattern of calling the setTimeout function with a string of arbitrary JavaScript, rather than the safer and more robust approach of passing a function pointer instead:

Every time I see `setTimeout("doSomething()", 1000);` instead of `setTimeout(doSomething, 1000);` I shed a tear (or maybe two or three, especially if the entire function is in quotes rather than just the name).

“Not so”, someone replied: the eval-like syntax is useful if you need to pass parameters along to the invoked function! Then another poster replied that you could just do that with an anonymous function:

// To pass params, use an anonymous function (best used on all browsers) 
window.setTimeout(function() { 
  myFunc(param1, param2); 
}, ms); 

This works fine if you're only invoking the function once. The problem with it has to do with how JavaScript scope works. This bit me a few days ago when trying to invoke a function with parameters culled from variables in a loop:

function processArray(arr) {
  var i=0, len = arr.length;
  for (i; i<len; i++) {
    window.setTimeout(function() {
        doSomething(arr[i]);
    }, 500);
  }
}

That function looks like it should work, but every time doSomething gets called, the parameter it receives is the final element in the array — by the time of the first invocation, it has already fallen out of the for loop and been incremented to arr.length.

You can rewrite this to make it work the right way fairly easily:

function processArray(arr) {
  if (arr.length) {
    window.setTimeout(function() {
        doSomething(arr.shift());
        processArray(arr);  // warning, recursion alert!
    }, 100);
  }
}

This is just a hastily-hacked-together function; in real production code you'd want to do something that didn't remove every item from the array. ;)

Happy Zelda Day!

Wednesday, February 22, 2012

I just realized that yesterday was Zelda Day, i.e. the 26th anniversary of the day Nintendo released the original Legend of Zelda for the NES.

As my long-time readers know, I have something of a preoccupation with this game. So how could I not mark its anniversary in some way? That's why today, I'm officially releasing Infinite Dungeon: Map Quest, a simple game that lays the foundation for something much more ambitious to come.

Enjoy.

Why do we need NaCl?

Tuesday, January 17, 2012

Just a quick post on some of the touted aspects of Google's Native Client (NaCl), and how they match up against the various browser-native alternatives. I'll have more to say on this soon.

Audio

Pepper audio API vs. Mozilla's Audio Data API

User input

NaCl input events vs. Mozilla's joystick API & mouse lock API (in fact, these are both part of a larger Mozilla project called Paladin that could be seen as something of a browser-native alternative to NaCl)

3D graphics

NaCl 3D graphics vs. WebGL

So why do we need NaCl, again?

JSConf.us 2011

Monday, May 2, 2011

Oregon or Bust!

This May my company gave me the opportunity to fly to Portland for a few days to be a part of the annual JSConf, JavaScript developers conference. I was grateful for the chance to get out of the office for a few days and take a step back to look at my day to day responsibilities from a slightly better vantage point. Plus, I got to hear from some pretty awesome speakers about the latest and greatest stuff happening in the Web-centric world, which never fails to inspire me to come back and write better code myself.

I took notes on a lot of the talks I attended, although sadly not all of them. I'll share some of those here, in more-or-less unfiltered form; I'll likely have more to say about specific aspects of the trip at a later date.

Day 1 (May 2nd)

Allen Pike: Making a JS meetup blow minds

Alan reviewed his efforts to bootstrap a JavaScript community in Vancouver. By organizing and shepherding VanJS (the Vancouver JavaScript developers meetup), he learned about the priciples that go into a successful local event:

  • should last around 45 minutes
  • should be 2 speakers (not everyone will connect with a single speaker, but the odds go up quite a bit with two, while not stretching things out too much)
  • should happen on a Monday through Thursday, not a weekend (makes people less likely to have other plans).
  • Speakers? Start with yourself, ask your friends to help (Don't go after the "big names" right away).
  • Make sure there's "beer" afterward (i.e. a pub of some kind within walking distance) — “this is what turns a group of people talking about code into a community” (it certainly seems to be a key part of the JSConf formula)

I definitely left this session inspired to try something like this in my own community. Stay tuned on that one.

Paolo Fragomeni: Rethinking Templating

  • Django-style templating, while currently acceptable, is “really not ok” (as it pollutes the HTML markup)
  • Introduced his own project, weld
  • Avoid "too much templating"
  • Instead, leverage your APIs and deliver data via AJAX/JSON

I can see where Paolo is coming from, but completely removing templating logic struck me as a bit extreme. Maybe my opinion will change over time, but right now I fail to see the benefit.

Day 2 (May 3rd)

Ray Morgan: App vs Web

Ray detailed lessons he'd learned at Zappos.com while working on their mobile offerings.

  • iPad app (and full API) developed in 8 weeks, after 3 weeks of experience
  • when developing an API, build an app to go along with it
  • “native apps aren't that hard to write”
  • live-coded a simple Objective-C app
  • crazy-weird syntax, but altogether not that hard (lots of good documentation)
  • instead of targeting Android, they targeted Mobile Web:
    • “Should mobile web really be trying to emulate native apps?”
    • it takes a lot of code to do things (even simple things) with mobile web
  • why not just semantic HTML?
  • progressive enhancement
  • you don't have to support everything, just your users
  • focus on usability
  • simplicity (“links should be links”)
  • flickr mobile website “captures what the web is about” (but back button behavior is still a little frustrating
  • Facebook provides all the core functionality in a mobile-friendly way

Adam Baldwin: Writing an (in)secure webapp in 3 easy steps

  • “I haven't secured it yet” — the problem is that “yet” never comes
  • devs should take a little more responsibility for security
  • #! navigation (e.g. "/#http://evilpacket.net/login") will work if it sets CORS headers right
  • don't roll your own encoders — there are others who've done it already
  • Content Security Policy (new feature in Firefox 4)
  • implementing browser-specific security policies may not completely cover you, but it puts you ahead of the guy who doesn't do anything
  • cross-site request forgery
  • clickjacking (x-frame-options allows you to specify which sites are allowed to frame you (if any)
  • cookies (HTTPOnly / secure)

Dan Webb: Pimp your JS library

  • “All programmers are API designers”
  • a beautiful API is what made jQuery so successful
  • 3 things:
    1. predictability
      • developers don't want complicated solutions when they go looking for a library
      • think about your audience
      • useCamelCase, yesReally
      • be careful with polyfills (your library probably isn't the right place to fix array.forEach)
      • borrow conventions from other popular JS libs (e.g. Raphael aping jQuery's attr())
    2. simplicity
      • Steve Krug's Don't Make Me Think
      • “Don't make me RTFM again...” (hint: your API is too big)
      • decide on sensible defaults, and what can be optional - called out the DOM .initMouseEvent() and .addEventListener() methods for overly-complex APIs - use options hashes (e.g. Dojo's style) for optional arguments
      • function calls should read well (compared DOM node replace functions in raw DOM vs Dojo vs jQuery)
    3. flexibility
      • how?
      • don't be like the 60-tool swiss army knife: you can't please everyone!
      • instead of infinitely growing your options hash, think about how to add hackability
      • have public, internal, and protected API levels (e.g. _internal vs public)
      • solve your own problems with your library

Matthew Eernisse: Heaven and Hell: JavaScript Everywhere

  • An AIR app doesn't equal “bad app” anymore than “native app” means “better”
  • problems with the AIR JS environment:
    • older Webkit
    • limited/nonstandard JS (no eval, sandboxBridge instead of postMessage, etc)
    • debugging is painful (no firebug/console)
  • limit use of privates: “sometimes you need to monkeypatch, so you can just ship”
  • test!
  • system tools: look at Jake
  • Node isn't the first SSJS... it's been around in various forms since the late 90s
  • if you aren't testing in the real environment, you aren't really testing

Rebecca Murphey: Modern Javascript

I missed this the first time around, but the Twitter feedback and positive buzz afterward were enormous, so it was one of the very first talks I watched when they started showing up on the JSConf channel on blip.tv. There's a great writeup of the talk here, Rebecca blogged about it later herself, and it's really, really worth your time to watch the video.

Dethe Elza: Introducing Waterbear

  • Alan Kay, who worked on the Alta, which in turn inspired the Mac, said: “The revolution hasn't happened yet”
  • promote a revolution in JS teaching (echoes of Rebecca Murphey's talk)
  • showed off Scratch, a visual code-builder
    • snap together building blocks
    • readable code
  • Waterbear is the same idea: drag and drop script blocks
  • Safari/Mobile Safari are the targets right now
  • children learn best by immersion, but the only thing we actually teach that way is language
  • making the world safe for “casual programmers” — those who only build little chunks when they need (e.g. a poll on a personal blog)

Thomas Fuchs: Zepto

  • what does a “real” computer have that a mobile device doesn't?
    • a fast & stable network connection
    • lots of storage
    • fast, multi-core CPUs
    • hardware-accelerated graphics
  • all the major JS libs were created before phones had web browsers of any significance
  • document.querySelectorAll returns a NodeList, not an array — otherwise it's pretty awesome
    • You can call [].slice.apply(nodelist) to get an array
  • native JSON is faster than library implementations
  • [1,2,3].forEach(alert)
  • why do we need a true mobile JavaScript framework? - more code causes longer download and init times - need something easy to extend - need a fallback for non-webkit browsers
  • Talked about Zepto
    • target size: 5k
    • jQuery-compatible API
    • uses webkit features whenever possible
    • easily replacable with full jQuery if needed
    • but it's 4.83kb vs 31.33k
  • “one more thing...”
  • classic frameworks have a lot of drawbacks on mobile:
    • they force you into an API
    • do all things and do them ok-ish
    • not modular (enough)
    • 25k+ minified/gzipped
    • many extensions are now available in latest DOM/JS
  • micro-frameworks, on the other hand:
    • do one thing, and do it really well
    • directly or loosely-coupled
    • no dependencies
    • small is beautiful (faster, easier to grok, fewer bugs, and you'll really grok JS)
  • Launched MicroJS.com: a simple list that tells you what's out there

Nikolai Onken: Mobile Deathmatch — (almost) all you need to know in 20 minutes

Nikolai talked about a way to do lightweight, inter-object communication, binding object state to the DOM. Three main points:

  1. Delegate
    • tiny library to approach event handling differently (it's basically just a mixin)
    • less overhead than dojo.connect
    • simple, clear implementation
    • more explicit than pub/sub
    • https://github.com/uxebu/delegate
    • showed an example using dojo.io.iframe and Delegate to check file upload progress (WOW)
  2. Data binding
    • based on delegate's event handling
    • no templating language
    • objects emit events on state change
    • data binding takes care of modifying DOM
  3. DOM events
    • binds native DOM events to object methods

Tobias Schneider: VNC with JavaScript

Tobias showed how you can create your own services on Node, built on libvnc. HOLY COW, his live-coding demo blew my mind! You should totally watch the video, it's pretty amazing what he's doing.

JavaScript: Say it like you mean it

The final talk was a fakeout by Peter Higgins, then Alex Russell and a co-worker from Google talked about the future of JavaScript, specifically introducing Traceur, their JS.Next->JS.Now compiler. Interesting stuff. I liked the gist of what Alex said:

language design is library design, library design is language design

Hi, I'm Buyog... I mean Ryan

I love that conferences provide the opportunity for "hallconf", i.e. the meetings between the scheduled meetings that are often our first "meatspace" interactions with people we'd previously known solely through their digital personas. That's pretty cool, because as awesome as the Internet is, there's something about physical interaction that just deepens relationships in important ways. I suspect it's buried deep in our shared subconscious as human beings.

Anyway, on this trip, I had the pleasure of meeting Carter Rabasa (IE Product Manager for Microsoft), Dustin Machi (Sitepen developer in Blacksburg Virginia, an area where we have some interest in relocating at some point), Rey Bango (Microsoft developer evangelist, jQuery committer, and Ajaxian), Daniel Lopez (front-end guy at Zappos.com), and Richard D. Worth (jQuery UI lead, Dev/Trainer at Boucoup, and founder of RewardJS). I even got to help Richard's RewardJS out a little with some code I hacked together for a leaderboard for that project, which became my first Github pull request! Pretty neat.

I hereby resolve...

Whenever I attend events like these, I always come away with a fresh view of code challenges I face back home in my role as my project's lead front-end guy. This trip was no exception: I see a lot of opportunities for improvement in the code I'm producing from day to day, and hope to pass along something of value to the rest of my team.