Looks can be deceiving

Looks about the same as last time, right? The visuals and interaction were designed to be almost identical, but the plumbing is very different.

The original, HTML DOM version used a table to render the game board. It's straight forward to let DOM elements handle layout and mouse interaction. Throw in a little CSS and you have a functional—albeit ugly—game.

But if one wants to make something really amazing, without fighting a Matryoshka doll of layout and CSS issues, one should leave the DOM behind.

Since I've decided leaving the third dimension for later, HTML canvas is an obvious choice. I also have a bit of of experience building games on canvas. See Agent 8 Ball and our work for Ze Frank.

Darts on Canvas

The working version of Dartsweeper does all of its drawing and click handeling via canvas. Canvas is an immediate mode graphics API. It's simple and straight-forward. It's also easy to have code complexity blow up once you start building anything complex.

When I was building out the UI layer for Throwing Stars for Mr. Frank, I wanted an object-oriented way to think about game elements. I wanted a star object and a wall object and a coin object that encapsulated the game physics and element rendering. So I put on my astronaut suit and built the PL javascript library. PL is short for Pixel Lab.

A big chunk of PL is under the retained namespace. It's a collection of types for retained mode graphics on canvas. I've ported most of the retained libraries to my dartlib project and they are used heavily in Sweeper.

Retained mode with Dartlib

I'll probably do a video at some point about the retained model in dartlib. The short version:
  • Stage: The glue between the DOM (a HTML Canvas element) and a root "element" in the retained world.
  • PElement: The base class for visual elements in the retained world.
    • Drawing is done with CanvasRenderContext2d. Super simple.
    • Zero or more transforms, which allow layout by the parent and fun effects
    • Parent and child pointers
      • Allow hit testing and mouse interaction
    • The P prefix stands for Pixel Lab. I'm trying to avoid naming conflicts with Element.
There's a bunch of other magic here, too. Mouse support. An attached property and attached event model. Support for correct Click behavior (mouse down the mouse up on the same element). Check out the samples in dartlib.

If you're feeling really adventurous, take a look at vote.dart. I have a lot of fun with retained graphics.


Cross-browser confusion

I've run into a couple of issues when trying to play the JS-compiled version of Dartsweeper on Firefox. 

In one case, I was using a webkit-specific version of requestAnimationFrame which doesn't exist on FireFox. Thankfully, Seth pointer me to the un-prefixed version of the API that works everywhere. A bug is open to removed the webkit prefixes.

In another case I discovered MouseEvent.offset[X|Y] don't exist in FireFox. There is a bug on this, too. I added a helper to dartlib provide the same functionality.

Growing pains with pub

I'm started tip-toeing into pub by migrating unit test code away from the copy in dartlib (which has been removed) to the SDK version.

Setting up pub has caused me a bit of stress since I use a custom homebrew formula to keep my SDK updated. Pub needs the DART_SDK environment variable to be set and homebrew installs versions in directories based on the version number. This causes a bit of headache as I need to delete the packages directory and rerun pub install every time I update my copy of Dart.

It's a bit of a headache, but it's purely related to how I install Dart. I'm hoping to tweak the homebrew formula to resolve this issue soon.

Next Steps

All of the work to migrate the game to canvas would be a bit silly if the output still looks like a poorly styled table.

After I finish up work storing high scores and created a touch-enabled interaction model, I'm going to jump into custom graphics, animation, and sound.

I'm excited. Stay tuned.

Oh, and you can help

All of the code is on github. File issues. Fork and add features. I'd love collaborators.

If you'd be interested in doing a hangout to discuss my graphics model, let me know.