Matt Snider JavaScript Resource

Understanding JavaScript and Frameworks

Tuesday, April 8, 2008

Movable DOM Node Widget

One of my favorite pastimes is playing and collecting video games, which combined with another of my passions, JavaScript, drives me to figure out ways to port simple gaming engines into JavaScript. JavaScript is not the best language for writing such engines (at least not in the browser), so I do not spend much time on this. However, I had a little time and revisited an old project, replacing the ancient coding with some simple YUI calls. When I wrote this, I was thinking of the original Dragon Warrior game, where you had a character that moved around the screen.

Think of the black rectangle as the character. Using YUI animation utility and a custom Object ‘Movable’, I listen to arrow keydown events and trigger animations on Movable. Because YUI manages duplicate animations on the same style of an Element (preventing it, until the previous animation completes), this was much simpler than code I had previously written. Also, the YUI animation code allows for diagonal movement if you press two perpendicular arrow keys within the half-second animation period. Try moving the black box around the screen on the Movable Object Test Page. Here is the code for the Movable Object:

Example 1: Movable Class

Core.Widget.Movable = function(id, useAnim) { // Local Variables var F = function() {}, node = $(id), that = null, anim = null; // shortcut for viewport size var getWSize = Core.Client.getViewportSize; // Public Variables F.prototype = { /** * Move the object down. * * @method down * @public */ down: function() { var r = Dom.getRegion(node), w = r.bottom - r.top, o = r.bottom, s = getWSize(); // prevent exceeding viewport height if (s.y < o + w) {o = s.y - w;} if (useAnim) { anim = new YAHOO.util.Anim(node, {top: {to: o}}, 1, YAHOO.util.Easing.easeOut); anim.animate(); } else { Dom.setStyle(node, 'top', o + 'px'); } }, /** * Move the object left. * * @method left * @public */ left: function() { var r = Dom.getRegion(node), w = r.right - r.left, o = r.left - w; // prevent exceeding viewport width if (0 > o - w) {o = 0;} if (useAnim) { anim = new YAHOO.util.Anim(node, {left: {to: o}}, 1, YAHOO.util.Easing.easeOut); anim.animate(); } else { Dom.setStyle(node, 'left', o + 'px'); } }, /** * Move the object right. * * @method right * @public */ right: function() { var r = Dom.getRegion(node), w = r.right - r.left, o = r.right, s = getWSize(); // prevent exceeding viewport width if (s.x < o + w) {o = s.x - w;} if (useAnim) { anim = new YAHOO.util.Anim(node, {left: {to: o}}, 1, YAHOO.util.Easing.easeOut); anim.animate(); } else { Dom.setStyle(node, 'left', o + 'px'); } }, /** * Move the object up. * * @method up * @public */ up: function() { var r = Dom.getRegion(node), w = r.bottom - r.top, o = r.top - w; // prevent exceeding viewport height if (0 > o - w) {o = 0;} if (useAnim) { anim = new YAHOO.util.Anim(node, {top: {to: o}}, 1, YAHOO.util.Easing.easeOut); anim.animate(); } else { Dom.setStyle(node, 'top', o + 'px'); } } }; // Scoped Operations that = new F(); return that; };

The ‘Movable’ class is designed to work with any DOM node that is absolutely positioned and smaller than the viewport. Simply pass the DOM node as the first parameter and whether you want the movements to be animated as the second. There is any number of reasons that you may need an Element on a page that can move up and down, based on its size, so you needn’t only think of it as part of a gaming engine. Keep in mind that I have used shorthand notation for ‘YAHOO.util.Dom’ (Dom), and ‘YAHOO.util.Dom.get’ ($). This widget also requires that you include ‘core.js‘.

Lastly, if you want to have it animate on the page, like in my example, you will need to use YUI Event package to listen to all keydown events on the ‘document’. Here is the code that I used:

Example 2: Document Keydown Listener

Event.addListener(document, 'keydown', function(e) { var test = Core.Widget.Movable(obj, true); switch (Event.getCharCode(e)) { case 37: // left arrow test.left(); break; case 38: // up arrow test.up(); break; case 39: // right arrow test.right(); break; case 40: // down arrow test.down(); break; } });

Again, I have shorthanded the ‘YAHOO.util.Event’ package to just ‘Event’. This code simply listens for all keydown events, ignoring all but the arrow keys. When any key is fired, it calls the appropriate method on ‘Movable’, which then handles the movement.

Now, the next step of the engine is to have the Object move over something, such as a map or a game board, firing custom events that the engine listens to. My next article will show how the ‘Movable’ object can be used to build a simple game.

posted by Matt Snider at 10:45 pm  

No Comments »

No comments yet.

RSS feed for comments on this post. TrackBack URI

Leave a comment

Powered by WordPress