From 0d82e84daf923a5167149a49c5017d59cabc9df2 Mon Sep 17 00:00:00 2001 From: Mike Gerwitz Date: Fri, 16 Mar 2012 21:36:57 -0400 Subject: [PATCH] Added basic animation support to MapRender This implementation is likely to change, but it does an excellent job bringing the map to life. The only frustrating part is that the game looks playable, but is not. --- lib/MapRender.js | 100 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 91 insertions(+), 9 deletions(-) diff --git a/lib/MapRender.js b/lib/MapRender.js index dc51667..39b9cc9 100644 --- a/lib/MapRender.js +++ b/lib/MapRender.js @@ -29,6 +29,12 @@ ltjs.MapRender = Class( 'MapRender', */ 'private const _LOCK': '__$$MapRenderLock$$', + /** + * Animation interval in milliseconds + * @type {number} + */ + 'private const _ANIM_INTERVAL': 200, + /** * 2d context to which map should be drawn @@ -48,6 +54,12 @@ ltjs.MapRender = Class( 'MapRender', */ 'private _tiles': {}, + /** + * Animation timer + * @type {number} + */ + 'private _animTimer': 0, + /** * Initialize renderer with a canvas context and a tile set @@ -114,6 +126,9 @@ ltjs.MapRender = Class( 'MapRender', { var c = this._ctxObj.canvas; + // clear any running animations + this._clearAnimation(); + // destroy the overlay canvas c.parentNode.removeChild( c ); @@ -168,6 +183,9 @@ ltjs.MapRender = Class( 'MapRender', sizey = size[ 1 ], i = objs.length, + // tiles to animate + anim = [], + // get the width and height from one of the tiles t = this._tiles.dirt.data, w = t.width, @@ -177,10 +195,12 @@ ltjs.MapRender = Class( 'MapRender', // see Map.getObjects()) while ( i-- ) { - var oid = objs[ i ], - tid = omap[ oid ], - x = ( Math.floor( i / sizex ) * w ), - y = ( ( i % sizey ) * h ); + var oid = objs[ i ], + tid = omap[ oid ], + tile = ( this._tiles[ tid ] || {} ).first, + + x = ( Math.floor( i / sizex ) * w ), + y = ( ( i % sizey ) * h ); // tunnels are handled a bit differently than other objects if ( map.isObjectTunnel( oid ) ) @@ -189,13 +209,28 @@ ltjs.MapRender = Class( 'MapRender', continue; } - this._drawTile( tid, x, y ); + // queue for animation if it contains more than a single frame + if ( this._canAnimate( tid ) ) + { + anim.push( [ tile, x, y ] ); + } + + this._drawTile( tile, x, y ); } + this._beginAnimation( anim ); + return this; }, + 'private _canAnimate': function( tid ) + { + var tdata = this._tiles[ tid ]; + return ( tdata.next !== tdata ); + }, + + /** * Draw the tile identified by the given id * @@ -209,12 +244,11 @@ ltjs.MapRender = Class( 'MapRender', * * @return {undefined} */ - 'private _drawTile': function( tid, x, y ) + 'private _drawTile': function( tile, x, y ) { - var tile = this._tiles[ tid ], - ctx = ( tile.masked ) ? this._ctxObj : this._ctx; + var ctx = ( tile.masked ) ? this._ctxObj : this._ctx; - ctx.putImageData( this._tiles[ tid ].first.data, x, y ); + ctx.putImageData( tile.data, x, y ); if ( tile.masked ) { @@ -246,5 +280,53 @@ ltjs.MapRender = Class( 'MapRender', // render the tile to the overlay canvas this._ctxObj.putImageData( tdata, x, y ); + }, + + + /** + * Begin basic tile animation + * + * At each animation interval, each tile will be advanced a single frame and + * rendered atop of the previous. + * + * @param {Array.>} anim array of tiles to + * animate; tdata,x,y + * + * @return {number} animation timer id + */ + 'private _beginAnimation': function( anim ) + { + var _self = this; + + // clear any existing rendering animations + this._clearAnimation(); + + return this._animTimer = setInterval( function() + { + var i = anim.length; + + while ( i-- ) + { + var cur = anim[ i ]; + + // draw next frame + cur[ 0 ] = cur[ 0 ].next; + _self._drawTile.apply( _self, anim[ i ] ); + } + }, this.__self.$( '_ANIM_INTERVAL' ) ); + }, + + + /** + * Clear any running animation timers + * + * It is important that this be done when a MapRender instance is done being + * used, or it will remain in memory indefinitely! + * + * @return {undefined} + */ + 'private _clearAnimation': function() + { + this._animTimer = +clearInterval( this._animTimer ); } } );