Archive for the ‘HTML5’ Tag

Color Transform for HTML5 Canvas

Interest in more information on applying color transformations with HTML5 Canvas came from my last post. If you’re coming from Flash, the concept of color transforms should be pretty familiar. The canvas method works pretty much the same way that Flash’s ColorTransform object worked (or what the color tint interface configured within the Flash IDE). All code needed is below; this snippit is largely based on the operation from easel.js.

// Apply color transform.
var r = 115, // Red tint (0-255)
    g = 208, // Green tint (0-255)
    b = 189, // Blue tint (0-255)
    t = 0.6, // Tint strength (0-1)
    i,
    ctx = document.getElementById('myCanvas').getContext('2d'), // Get the drawing context of your canvas element.
    img = ctx.getImageData(0, 0, 100, 100), // Pull a rectangle of image data from context
    data = img.data, // Image image data array.
    len = data.length; // Length of data array.

// Loop through image data array.
// Apply color trasform to each block of RGBA values.
// Applied as: c = c * cmodifier + coffset.
for (i = 0; i < len;) {
    data[i] = data[i++] * (1-t) + (r*t);
    data[i] = data[i++] * (1-t) + (g*t);
    data[i] = data[i++] * (1-t) + (b*t);
    i++; //data[i] = data[i++] * 1 + 0; << skip alpha component. Adjust as needed.
}

// Restore image data within the canvas.
ctx.putImageData(img, 0, 0);

Once Flash, Now JavaScript

The fishing mini-game featured in “What Makes You Tick: A Stitch in Time” is back, and this time it’s not running in Flash. It’s running in HTML5 using the canvas tag… and it was a pretty easy migration. First, have a look at the Flash and HTML versions of the game; they’re at:

Flash: http://www.lassiegames.com/games/stitch_fishing/play_1024.php
HTML5 Canvas: http://www.lassiegames.com/tests/fishing/

Pretty cool, right? There’s no two ways about it, the canvas tag is quite capable with fast image compositing. So, let’s have a look at how this Flash game turned Canvas.

Interface graphics

There are several big graphics used in the game’s interface. The background image and the intro screen are both just big image plates applied to HTML elements. All interface elements (buttons, text displays) are just HTML. When the actual game starts running, a full-screen Canvas element is placed on top of the background image, and the game starts drawing itself at 30 frames a second. Once the game ends, the canvas is pulled from the DOM and we go back to simple HTML/CSS layout for the replay options.

Basic game graphics

The game graphics all draw from a single sprite sheet, which you can see here. You’ll see that there’s one of each of the fish (green and yellow), multi-frame animation states for the animating jellyfish and the fishing net, and then some assorted interface elements. In most cases, rectangular regions are pulled from this sprite sheet and composited directly to the canvas on the fly. The big exception here are the green fish…

As the game runs, notice that the green fish have an implied visual depth: they get smaller and tinted with a pale shade of green further down in the layer stack. This effect is achieved with scale and pixel color transformations, both of which are expensive operations to be running every frame. However, these effects can be pre-rendered. Scroll down and look below the fishing game on the page. You should see a line of 15 green fish images, each getting slightly bigger and darker from left-to-right. These are the actual fish images being used within the game. As the game launches, the original green fish image is pulled from the sprite sheet and rendered with transformations onto these 15 individual canvas elements which are created on the fly. Then as the game runs, the pre-rendered fish images can be quickly composited into the game canvas without re-processing these additional transformations. Keep in mind that those individual fish images technically do NOT need to be displayed within the DOM for this to work (they’re just being displayed for demonstration purposes). Normally, you’d just store these pre-rendered elements within memory.

As for the fishing line, that’s just a simple vector arc drawn from a fixed point at the top down to the dynamically plotted mouse position. A fixed control point for the line’s arc is set a few hundred pixels below the origin to create a curve.

Animations

Animations are certainly the trickiest part of post-Flash graphics. Again, if you refer to the game’s sprite sheet you’ll see multiple graphical states drawn for the undulating jellyfish and the lifting net. The concept of animation is pretty simple: we’re just going to change the rectangular region pulled from the sprite sheet every few frames. The implementation is a bit trickier though. Animations generally require an independent interval which runs at a fraction of the main framerate; this allows objects to move around the screen at 30fps while only changing visual state, say, every three frames (10fps). One trick here is to use a modulus (division remainder) of the main clock to maintain a subset interval. Mind you, I was experimenting with some home brew animation techniques while building the Fishing game so reinvented a few wheels. There are plenty of JavaScript-based animation frameworks (like Cocos 2D) which will take care of this grunt work for you.

Sound

Now, I will admit that I cheated on the audio. I was underwhelmed by the capabilities of the HTML5 audio tag for playing sound effects in rapid succession, so I just set up a Flash player that plays effects at the command of JavaScript.

Program

All told, I ended up keeping the JavaScript architecture very similar to the original Flash architecture. In Flash, there’s a HookableObject abstract that extends into several implementations (Fish, Jellyfish, Boot, etc). In JavaScript, this same mapping was used with HookableObject serving as the prototype for Fish and Jellyfish. Beyond that, most object relationships between, say, Hook > Fish > Net didn’t really need to change. In fact, the single biggest change required involved the display list. In Flash, it was easy to reconfigure/reorder the pond as needed during an update pass, and then see all graphics magically update in accordance during Flash’s next render pass. This was useful when a fish swam off screen… anytime a fish left play and was ready for reset, there was a small probability offered for it to upgrade itself to “gold” status and swim the next pass as a bonus fish at the top of the stack. Unfortunately, this was a lot more complicated in JavaScript where I was trying to perform application update and rendering in a single pass, and therefore update order and rendering order were dependent upon one another. Rather than splitting rendering into a second pass, I opted to just change the delegation of bonus fish so that only fish at the top of the stack were eligible for upgrade to gold status.

So, that’s the gist of the HTML5 fishing game. Fun stuff. Enjoy the game, and feel free to download the complete project code from its GitHub repo.