Palagpat Coding

Fun with JavaScript, game theory, and the occasional outbreak of seriousness

Tuesday, May 05, 2009

Cloning Zelda, part 5: Redefining the Sprite classes

Previous posts in this series: Part 1 | Part 2 | Part 3A | Part 3B | Part 4A | Part 4B | Part 4C

Too long since my last post. Moving forward, I'm going to establish a schedule for blog updates, and will work to maintain it. More on that soon.

As I've mentioned previously, my sprite classes had become something of a house of cards, which only held together in Firefox and collapsed in every other browser. Clearly, not what I was shooting for.

I also blogged last time that I got the chance to speak with Peter Higgins, the project lead for the Dojo Toolkit, at the JSConf developers' conference a few weekends ago. With his help, I've finally managed to wrap my head around how the Dojo class loader works, and have used my newfound knowledge to rebuild the sprite engine for Canvassa. (whew! that's a lot of links!)

Bottom line, for the short-attention-span crowd: click here to view the new sprite test harness, which shows off a couple of the new engine's features:

  • True class inheritance and dependency resolution (Player and Monster classes are defined in separate files from the base Sprite class)
  • Animation state and timing "cooked in" to the base classes (press the number keys to see the animations each sprite class defines)
  • Selective property overriding in derived classes (note the different walking speeds of the sprites)
  • Should be much more cross-browser compatible (Safari/Chrome/Opera users: please let me know if it doesn't work for you!)

So, the key to Dojo's load system are three commands: dojo.require, dojo.provide, and dojo.declare. The way it works is pretty brilliant: when dojo.require is called, the loader code looks to see if the requested class name exists yet in the global namespace. If not, it goes out and looks on the server for a path that matches the requested class's namespace, and if found, a JavaScript file named the same as the class in question. For example, this code:

  dojo.require("foo.bar.ClassName");

...will start looking in the location of the Dojo module, trying to find a folder named foo, with a subfolder of bar. If found, it then looks in that folder for a file named ClassName.js. If found, it then uses the DOM to dynamically insert a new <script> block into the current page's header, referencing the path foo/bar/ClassName.js. The ClassName.js file, in turn, begins by calling dojo.provide("foo.bar.ClassName") to indicate its intent, and dojo.declare(...) to actually define the class. The critical part that Peter helped me understand is that, since this is essentially injecting new code into the header at runtime, the class won't be immediately available... explaining why my code kept blowing up when I tried something like this:

  dojo.require("loc.Game");
  var game = new loc.Game();

The way to do what I was trying to do, Peter told me, was to leverage the dojo.addOnLoad() method. This registers a callback function to be executed when all requested classes have been fully loaded. The cool thing about this, Peter told me, was that you could actually chain multiple require() / addOnLoad() calls, and Dojo will do the right thing!

  dojo.require("namespace.Class1");
  dojo.addOnLoad( function() { console.log("Class 1 loaded."); } );

  dojo.require("namespace.Class2");
  dojo.addOnLoad( function() { console.log("Class 2 loaded."); } );

  dojo.require("namespace.Class3");
  dojo.addOnLoad( function() { console.log("Class 3 loaded."); } );

I mean, really: how cool is THAT?!? (answer: very.)

So now, armed with the knowledge of how to make Dojo load my classes in the proper order, I'll be able to move forward again. I should be able to leverage most of the old code from parts 2 through 4 of this series, albeit with slight tweaks to fit the new Sprite class model. And therein lies my love for Dojo: it formalizes things I already intuitively know how to do, and makes them work across all potential platforms, without any additional effort on my part. If you're not using Dojo or any other JavaScript framework or toolkit (e.g. MooTools / jQuery / YUI / etc.), why the heck not? It makes coding for the web a much more rewarding, and productive, experience.

Labels: , , ,

0 Comments:

Post a Comment

Subscribe to Post Comments [Atom]

<< Home