I've been playing around with AS 3.0, and I will be the first to admit that I feel like a total nubb as I try to figure out my own set of new "best practices." Apart of my tinkerings have involved putting together a test project. This test project needs an animated sprite class, so I wrote up a quick one this afternoon.
You're free to use this code however you want, rename it, resell it, whatever. I'm hoping to gain some insights into how best to optomize it from people more smarter/experienced than myself (yes, you who is reading this).
If it is a complete piece of crap, then please, tear it to shreds, but do so in this thread so I can figure out why it is crap so I can fix it.
The part of it that makes me the most uncomfortable is how I update frames. I just removeChild the current, and addChild the next in the sequence. I can't help but feel this is suboptimal.
Without further adieu:
Code:
package {
import flash.display.*;
import flash.events.*;
import flash.utils.getTimer;
// Usage: gotoAndStop/gotoAndPlay are 0-indexed
// time is in milliseconds
public class AnimatedSprite extends Sprite
{
public static const k_loopForever = -1;
public static const k_loopOnce = 0;
var m_frames : Array = new Array();
var m_activeFrameIndex : int;
var m_activeObject : DisplayObject;
var m_timeOfLastUpdate : int;
var m_timeBetweenFrames : int;
var m_accumulatedTime : int;
var m_isPaused : Boolean;
var m_desiredLoopCount : int;
var m_actualLoopCount : int;
function AnimatedSprite( a_frames : Array, a_timeBetweenFrames : int, a_desiredLoopCount : int = k_loopForever )
{
m_frames = a_frames;
m_timeBetweenFrames = a_timeBetweenFrames;
m_desiredLoopCount = a_desiredLoopCount;
if( m_desiredLoopCount < k_loopForever )
{
trace( "AnimatedSprite.constructor, desired loop count cannot be negative.");
m_desiredLoopCount = k_loopForever;
}
initialize();
}
public function dispose()
{
m_activeObject = null;
m_frames.splice( 0 );
m_frames = null;
}
public function stop()
{
m_isPaused = true;
}
public function play()
{
m_isPaused = false;
}
public function gotoAndStop( a_frameNumber : int )
{
gotoAndPlay( a_frameNumber );
stop();
}
public function gotoAndPlay( a_frameNumber : int )
{
if( a_frameNumber < 0 && a_frameNumber >= m_frames.length )
{
trace( "AnimatedSprite.gotoAndPlay, frame out of range." );
a_frameNumber = 0;
}
m_activeFrameIndex = a_frameNumber;
forceUpdate();
}
public function getCurrentFrame() : int
{
return m_activeFrameIndex;
}
// Private Functions - Nothing to see here, move along now...
private function handleFrame( a_event : Event )
{
var deltaTime : int = calculateDeltaTime();
if( m_isPaused ) return;
m_accumulatedTime += deltaTime;
if( m_accumulatedTime < m_timeBetweenFrames )
{
// We haven't accrued enough time to tick the sprite yet
return;
}
m_accumulatedTime -= m_timeBetweenFrames;
m_activeFrameIndex++;
if( m_activeFrameIndex >= m_frames.length )
{
m_actualLoopCount++;
if( m_desiredLoopCount == k_loopForever || m_actualLoopCount <= m_desiredLoopCount )
{
m_activeFrameIndex = 0;
}
else
{
m_activeFrameIndex = m_frames.length - 1;
stop();
}
}
updateFrame();
}
private function forceUpdate()
{
m_accumulatedTime = 0;
updateFrame();
}
private function initialize()
{
m_actualLoopCount = 0;
m_accumulatedTime = 0;
m_isPaused = false;
m_activeObject = null;
m_activeFrameIndex = 0;
m_timeOfLastUpdate = getTimer();
drawActiveFrame( );
addEventListener( Event.ENTER_FRAME, handleFrame, false, 0, true );
}
private function calculateDeltaTime() : int
{
var currentTime : int = getTimer();
var deltaTime : int = currentTime - m_timeOfLastUpdate;
m_timeOfLastUpdate = currentTime;
return deltaTime;
}
private function updateFrame()
{
undraw();
drawActiveFrame();
}
private function undraw()
{
removeChild( m_activeObject );
}
private function drawActiveFrame( )
{
m_activeObject = m_frames[ m_activeFrameIndex ];
addChild( m_activeObject );
}
}
}
and the example code:
Code:
var frames : Array = new Array();
frames.push( new Bitmap( new ex1() ) ); // Ex1 is a bitmapData
frames.push( new Bitmap( new ex2() ) ); // Ex2 is a bitmapData
frames.push( new Bitmap( new ex3() ) ); // Ex3 is a bitmapData
frames.push( new Bitmap( new ex4() ) ); // Ex4 is a bitmapData
var animatedSprite : AnimatedSprite = new AnimatedSprite( frames, 1000 );
addChild( animatedSprite );
animatedSprite.x = 150;
animatedSprite.y = 150;