Skip to content

Commit

Permalink
added MovieClip class (closes #5)
Browse files Browse the repository at this point in the history
  • Loading branch information
PrimaryFeather committed Jul 26, 2011
1 parent e9b29a8 commit 12011b1
Show file tree
Hide file tree
Showing 9 changed files with 323 additions and 5 deletions.
Binary file added samples/demo/media/audio/step.mp3
Binary file not shown.
19 changes: 19 additions & 0 deletions samples/demo/src/Assets.as
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package
{
import flash.display.Bitmap;
import flash.media.Sound;
import flash.utils.Dictionary;

import starling.textures.Texture;
Expand Down Expand Up @@ -51,9 +52,15 @@ package
[Embed(source="../media/textures/atlas.png")]
public static const AtlasTexture:Class;

// Sounds

[Embed(source="../media/audio/step.mp3")]
public static const StepSound:Class;

// Texture cache

private static var sTextures:Dictionary = new Dictionary();
private static var sSounds:Dictionary = new Dictionary();
private static var sTextureAtlas:TextureAtlas;

public static function getTexture(name:String):Texture
Expand All @@ -67,6 +74,13 @@ package
return sTextures[name];
}

public static function getSound(name:String):Sound
{
var sound:Sound = sSounds[name] as Sound;
if (sound) return sound;
else throw new ArgumentError("Sound not found: " + name);
}

public static function getTextureAtlas():TextureAtlas
{
if (sTextureAtlas == null)
Expand All @@ -78,5 +92,10 @@ package

return sTextureAtlas;
}

public static function prepareSounds():void
{
sSounds["Step"] = new StepSound();
}
}
}
5 changes: 5 additions & 0 deletions samples/demo/src/Game.as
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package
import scenes.AnimationScene;
import scenes.BenchmarkScene;
import scenes.CustomHitTestScene;
import scenes.MovieScene;
import scenes.Scene;
import scenes.TextureScene;
import scenes.TouchScene;
Expand All @@ -23,6 +24,9 @@ package

public function Game()
{
// sound initialization takes a moment, so we prepare them here
Assets.prepareSounds();

var bg:Image = new Image(Assets.getTexture("Background"));
addChild(bg);

Expand All @@ -37,6 +41,7 @@ package
["Multitouch", TouchScene],
["Animations", AnimationScene],
["Custom hit-test", CustomHitTestScene],
["Movie Clip", MovieScene],
["Benchmark", BenchmarkScene]
];

Expand Down
61 changes: 61 additions & 0 deletions samples/demo/src/scenes/MovieScene.as
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package scenes
{
import flash.media.Sound;

import starling.core.Starling;
import starling.display.MovieClip;
import starling.events.Event;
import starling.text.TextField;
import starling.utils.HAlign;
import starling.utils.VAlign;

public class MovieScene extends Scene
{
private var mMovie:MovieClip;

public function MovieScene()
{
var description:String = "Animation provided by angryanimator.com";
var infoText:TextField = new TextField(300, 30, description, "Arial", 13);
infoText.x = infoText.y = 10;
infoText.vAlign = VAlign.TOP;
infoText.hAlign = HAlign.CENTER;
addChild(infoText);

var frames:Array = Assets.getTextureAtlas().getTextures("walk_");
mMovie = new MovieClip(frames, 12);

// add sounds
var stepSound:Sound = Assets.getSound("Step");
mMovie.setFrameSound(1, stepSound);
mMovie.setFrameSound(7, stepSound);

// move the clip to the center and add it to the stage
mMovie.x = Constants.CenterX - int(mMovie.width / 2);
mMovie.y = Constants.CenterY - int(mMovie.height / 2);
addChild(mMovie);

// like any animation, the movie needs to be added to the juggler!
// this is the recommended way to do that.
addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
addEventListener(Event.REMOVED_FROM_STAGE, onRemovedFromStage);
}

private function onAddedToStage(event:Event):void
{
Starling.juggler.add(mMovie);
}

private function onRemovedFromStage(event:Event):void
{
Starling.juggler.remove(mMovie);
}

public override function dispose():void
{
removeEventListener(Event.REMOVED_FROM_STAGE, onRemovedFromStage);
removeEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
super.dispose();
}
}
}
6 changes: 5 additions & 1 deletion starling/src/starling/display/Image.as
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,11 @@ package starling.display
public function get texture():Texture { return mTexture; }
public function set texture(value:Texture):void
{
if (value) mTexture = value;
if (value)
{
mTexture = value;
createVertexBuffer();
}
else throw new ArgumentError("Texture cannot be null");
}
}
Expand Down
228 changes: 228 additions & 0 deletions starling/src/starling/display/MovieClip.as
Original file line number Diff line number Diff line change
@@ -0,0 +1,228 @@
package starling.display
{
import flash.media.Sound;

import starling.animation.IAnimatable;
import starling.events.Event;
import starling.textures.Texture;

[Event(name="movieCompleted", type="starling.events.Event")]
public class MovieClip extends Image implements IAnimatable
{
private var mTextures:Vector.<Texture>;
private var mSounds:Vector.<Sound>;
private var mDurations:Vector.<Number>;

private var mDefaultFrameDuration:Number;
private var mTotalTime:Number;
private var mCurrentTime:Number;
private var mCurrentFrame:int;
private var mLoop:Boolean;
private var mPlaying:Boolean;

public function MovieClip(textures:Array, fps:Number=12)
{
if (textures.length > 0)
{
super(textures[0]);
mDefaultFrameDuration = 1.0 / fps;
mLoop = true;
mPlaying = true;
mTotalTime = 0.0;
mCurrentTime = 0.0;
mCurrentFrame = 0;
mTextures = new <Texture>[];
mSounds = new <Sound>[];
mDurations = new <Number>[];

for each (var texture:Texture in textures)
addFrame(texture);
}
else
{
throw new ArgumentError("Empty texture array");
}
}

// frame manipulation

public function addFrame(texture:Texture, sound:Sound=null, duration:Number=-1):void
{
addFrameAt(numFrames, texture, sound, duration);
}

public function addFrameAt(frameID:int, texture:Texture, sound:Sound=null,
duration:Number=-1):void
{
if (frameID < 0 || frameID > numFrames) throw new ArgumentError("Invalid frame id");
if (duration < 0) duration = mDefaultFrameDuration;
mTextures.splice(frameID, 0, texture);
mSounds.splice(frameID, 0, sound);
mDurations.splice(frameID, 0, duration);
mTotalTime += duration;
}

public function removeFrameAt(frameID:int):void
{
if (frameID < 0 || frameID >= numFrames) throw new ArgumentError("Invalid frame id");
mTotalTime -= getFrameDuration(frameID);
mTextures.splice(frameID, 1);
mSounds.splice(frameID, 1);
mDurations.splice(frameID, 1);
}

public function getFrameTexture(frameID:int):Texture
{
if (frameID < 0 || frameID >= numFrames) throw new ArgumentError("Invalid frame id");
return mTextures[frameID];
}

public function setFrameTexture(frameID:int, texture:Texture):void
{
if (frameID < 0 || frameID >= numFrames) throw new ArgumentError("Invalid frame id");
mTextures[frameID] = texture;
}

public function getFrameSound(frameID:int):Sound
{
if (frameID < 0 || frameID >= numFrames) throw new ArgumentError("Invalid frame id");
return mSounds[frameID];
}

public function setFrameSound(frameID:int, sound:Sound):void
{
if (frameID < 0 || frameID >= numFrames) throw new ArgumentError("Invalid frame id");
mSounds[frameID] = sound;
}

public function getFrameDuration(frameID:int):Number
{
if (frameID < 0 || frameID >= numFrames) throw new ArgumentError("Invalid frame id");
return mDurations[frameID];
}

public function setFrameDuration(frameID:int, duration:Number):void
{
if (frameID < 0 || frameID >= numFrames) throw new ArgumentError("Invalid frame id");
mTotalTime -= getFrameDuration(frameID);
mTotalTime += duration;
mDurations[frameID] = duration;
}

// helper methods

private function updateCurrentFrame():void
{
texture = mTextures[mCurrentFrame];
}

private function playCurrentSound():void
{
var sound:Sound = mSounds[mCurrentFrame];
if (sound) sound.play();
}

// playback methods

public function play():void
{
mPlaying = true;
}

public function pause():void
{
mPlaying = false;
}

public function stop():void
{
mPlaying = false;
currentFrame = 0;
}

// IAnimatable

public function advanceTime(passedTime:Number):void
{
if (mLoop && mCurrentTime == mTotalTime) mCurrentTime = 0.0;
if (!mPlaying || passedTime == 0.0 || mCurrentTime == mTotalTime) return;

var i:int = 0;
var durationSum:Number = 0.0;
var previousTime:Number = mCurrentTime;
var restTime:Number = mTotalTime - mCurrentTime;
var carryOverTime:Number = passedTime > restTime ? passedTime - restTime : 0.0;
mCurrentTime = Math.min(mTotalTime, mCurrentTime + passedTime);

for each (var duration:Number in mDurations)
{
if (durationSum + duration >= mCurrentTime)
{
if (mCurrentFrame != i)
{
mCurrentFrame = i;
updateCurrentFrame();
playCurrentSound();
}
break;
}

++i;
durationSum += duration;
}

if (previousTime < mTotalTime && mCurrentTime == mTotalTime &&
hasEventListener(Event.MOVIE_COMPLETED))
{
dispatchEvent(new Event(Event.MOVIE_COMPLETED));
}

advanceTime(carryOverTime);
}

public function get isComplete():Boolean
{
return false;
}

// properties

public function get totalTime():Number { return mTotalTime; }
public function get numFrames():int { return mTextures.length; }

public function get loop():Boolean { return mLoop; }
public function set loop(value:Boolean):void { mLoop = value; }

public function get currentFrame():int { return mCurrentFrame; }
public function set currentFrame(value:int):void
{
mCurrentFrame = value;
mCurrentTime = 0.0;

for each (var duration:Number in mDurations)
mCurrentTime += duration;

updateCurrentFrame();
}

public function get fps():Number { return 1.0 / mDefaultFrameDuration; }
public function set fps(value:Number):void
{
var newFrameDuration:Number = value == 0.0 ? Number.MAX_VALUE : 1.0 / value;
var acceleration:Number = newFrameDuration / mDefaultFrameDuration;
mCurrentTime *= acceleration;
mDefaultFrameDuration = newFrameDuration;

for (var i:int=0; i<numFrames; ++i)
setFrameDuration(i, getFrameDuration(i) * acceleration);
}

public function get isPlaying():Boolean
{
if (mPlaying)
return mLoop || mCurrentTime < mTotalTime;
else
return false;
}
}
}
1 change: 1 addition & 0 deletions starling/src/starling/events/Event.as
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ package starling.events
public static const REMOVED:String = "removed";
public static const REMOVED_FROM_STAGE:String = "removedFromStage";
public static const TRIGGERED:String = "triggered";
public static const MOVIE_COMPLETED:String = "movieCompleted";

private var mTarget:EventDispatcher;
private var mCurrentTarget:EventDispatcher;
Expand Down

0 comments on commit 12011b1

Please sign in to comment.