Archive for the 'Open Source Projects' Category

04th Sep 2008

Tween Sequencer

Many of the projects I have done have included creating some sort of repeating sequence of tweens. In my early projects I would trigger the next tween using the finished event for each tween. This sucked.

So recently I had some time and decided to take a crack at creating a tween sequencing class. Basic idea being that I add a sequence of tweens to a object and then just call a start function to trigger the sequence.

My first idea was to create a collection of tween objects and store references to them in an array. This led me to com up with this:

package com.vfd.animation.tweens{
import fl.transitions.TweenEvent;
import fl.transitions.Tween;
public class TweenSequencer {
private var _tweens:Array=new Array ;

private var index:Number=0;
public var loop:Boolean=false;
public function TweenSequencer() {
trace(“New Tween Sequencer”);
}
public function addTween(tween:Tween):void {
tween.stop();
tween.addEventListener(TweenEvent.MOTION_FINISH,nextTween);
this._tweens.push(tween);
}
public function removeTween(tween:Tween):void {
for (var i:Number=0; i < this._tweens.length; i++) {
if (this._tweens[i] == tween) {
this._tweens[i].removeEventListener(TweenEvent.MOTION_FINISH,nextTween);
this._tweens.splice(i,1);
break;
}
}
}
public function start():void {
this.startTween();
}
public function stop():void {
this.pause();
this.reset();
}
public function pause():void {
if (this._tweens[this.index]) {
this._tweens[this.index].stop();
}
}
private function nextTween(event:TweenEvent):void {
trace(“Index before ” + this.index);
trace(“Loop : ” + this.loop);
this.index++;
if (this.loop && this.index >= this._tweens.length) {
this.reset();
}
trace(“Index after ” + this.index);
this.startTween();

}
private function startTween() {
if (this._tweens[this.index]) {
this._tweens[this.index].play();
} else {
this.reset();
}
}
private function reset():void {
this.index=0;
}
}//end class
}//end package

The basic idea worked, but I ran into a couple of problems. I was testing this with a basic ball. I placed the ball in the top right corner of the screen. Every time I ran the thing it would play the tweens in the correct sequence, but the ball always started in the bottom right corner of the screen making the first run through the sequence incorrect. However, after the first run through it played as expected.

This took me a while to figure out, but as it turns out that when I created the tweens, even though I immediately stopped them, it was setting the properties of the ball to the start values of the second set of tweens that were applied to the x and y coordinates.

I tried all sorts of variations including writing my own tween class that overrode the starting behaviors of the standard tween class and I still ended up with the same results (though it is entirely possible that I missed something simple).

I did turn out that if I explicitly set the x and y coordinates of the clip after creating the tweens, it worked as expected. However, I was only testing with many tweens applied to one object. If I was applying tweens to multiple objects I would have to reset all of them and having to explicitly set the coordinates defeated the purposes of placing them on the stage where I wanted them to begin with. Additionally, I ran into this problem with tweens applied to x and y, but if there are other properties that behaved the same way, I would have to reset those as well. This class was intended to make this process sequencing tweens easier, not simply introduce a new set of headaches.

After some time I came up with the idea of using a single tween inside of the sequencer class. Instead of storing multiple tween instances, I would just store sequence of properties and values that I wanted to tween an update the single tween instance. this would keep the tweens property settings from conflicting with one another and throwing the sequence off. This lead to:

package com.vfd.animation.tweens{
import fl.transitions.TweenEvent;
import fl.transitions.Tween;
import flash.display.Sprite;
public class TweenSequencer {
private var _tweens:Array=new Array();
private var tween:Tween;
private var index:Number=0;
public var loop:Boolean=false;
private var placeHolderSprite:Sprite = new Sprite();
public function TweenSequencer() {
trace(“New Tween Sequencer”);
this.tween = new fl.transitions.Tween(this.placeHolderSprite,”alpha”,null,1,1,1,true);
this.tween.stop();
this.tween.addEventListener(TweenEvent.MOTION_FINISH,nextTween);
}
public function addTween(obj:Object, prop:String, easing:Function, begin:Number, end:Number, duration:Number, useSeconds:Boolean = false):void {
this._tweens.push(arguments);
}
public function start():void {
this.startTween();
}
public function stop():void {
this.tween.rewind();
this.reset();
}
public function pause():void {
this.tween.stop();
}
private function nextTween(event:TweenEvent):void {
this.index++;
if (this.loop && this.index >= this._tweens.length) {
this.reset();
}
this.startTween();

}
private function startTween() {
this.tween.stop();
if (this._tweens[this.index]) {
this.tween.obj = this._tweens[this.index][0];
this.tween.prop = this._tweens[this.index][1];
if (this._tweens[this.index][2] is Function) {
this.tween.func = this._tweens[this.index][2];
}
this.tween.begin = this._tweens[this.index][3];
this.tween.finish = this._tweens[this.index][4];
this.tween.duration = this._tweens[this.index][5];
this.tween.useSeconds = this._tweens[this.index][6];
this.tween.start();
} else {
this.reset();
}
}
private function reset():void {
this.index=0;
}
public function reverse() {
this._tweens.reverse();
}
}//end class
}//end package

So now this:

import com.vfd.animation.tweens.TweenSequencer;
var ts:TweenSequencer = new TweenSequencer();
ts.loop = true;
ts.addTween(ball, “alpha”, null, 0,1,2,true);
ts.addTween(ball, “x”, null, 130,300,2,true);
ts.addTween(ball, “y”, null, 130,300,2,true);
ts.addTween(ball, “x”, null, 300,130,2,true);
ts.addTween(ball, “y”, null, 300,130,2,true);
ts.addTween(ball, “alpha”, null, 1,0,2,true);
ts.start();

Produces this:

Posted by Posted by Jeremy Wischusen under Filed under ActionScript 3, OOP, Open Source Projects Comments 5 Comments »

15th Aug 2008

Hold on a Second

You can find a lot of tween libraries for AS2 and AS3. Many of these include some sort of mechanism for delaying the start of a tween. A while back I took my own shot at this based off of another class that I found and came up with:

import mx.transitions.Tween;
class com.vfd.animation.tweens.DelayedTween extends Tween{

private var intervalID:Number
private var delay:Number = 0;

public function DelayedTween(object, property, easingFunction, start, end, duration, useSeconds, delay) {

super(object, property, easingFunction, start, end, duration, useSeconds);
this.delay = Math.abs(delay*1000);
this.setDelay();

}
private function start() {

}

private function setDelay() {
if (this.delay > 0) {
this.intervalID = setInterval(this, “startAnimation”, this.delay);
}else {
this.startAnimation();
}
}

private function startAnimation() {
clearInterval(this.intervalID);
super.start();
}

}

This was more or less a simple copy of the class I had found. I got a chance to look at this again today and realized I could simplify it a bit. I ended up with:

/**
* @author Jeremy Wischusen
* This class allows for a delay before starting the animation.
*/
import mx.transitions.Tween;
import mx.utils.Delegate;
class com.vfd.animation.tweens.DelayedTween extends Tween {
/*
Holds the number of seconds to wait before starting the animation.
*/
private var _delay:Number = 0;
/*
Instance variable holding a reference to the start function of the Tween class.
This is needed due to scoping issues when using setTimeout.
*/
private var superStart:Function;
public function DelayedTween(object, property, easingFunction, start, end, duration, useSeconds, delay) {
this.delay = delay;
/*Use the Delegate class to create a reference back to the tween start funciton
that can be used with setTimeout. */
this.superStart = Delegate.create(super, super.start);
super(object,property,easingFunction,start,end,duration,useSeconds);
}
/*Override the default start function so that the delay can be applied.*/
public function start() {
if (this._delay>0) {
_global.setTimeout(this.superStart,this._delay);
} else {
super.start();
}
}
/*Setter function for delay attribute*/
public function set delay(seconds:Number){
this._delay = Math.abs(seconds*1000);
}
}

As you can see, I reduced the number of functions, used the simpler setTimeOut and rely more on inheritance and overriding than in the previous version. I also decided to make and AS3 version.

package com.vfd.animation.tweens{
import fl.transitions.Tween;
import flash.utils.setTimeout;
/**
* @author Jeremy Wischusen
* This class allows for a delay before starting the animation.
*/
public class DelayedTween extends Tween {
/*
Holds the number of seconds to wait before starting the animation.
*/
private var _delay:Number = 0;
public function DelayedTween(object, property, easingFunction, start, end, duration, useSeconds, delay) {
this.delay = delay ;
super(object,property,easingFunction,start,end,duration,useSeconds);
}
/*Override the default start function so that the delay can be applied.*/
public override function start():void {
if (this._delay>0) {
setTimeout(super.start,this._delay);
} else {
super.start();
}
}
/*Setter function for delay attribute*/
public function set delay(seconds:Number):void {
this._delay = Math.abs(seconds*1000);
}
}
}

I have noticed that occasionally the compiler spits out:
The superconstructor must be called first in the constructor body.

If you place the super constructor before the delay variable is set, the tween just starts immediately since the variable has a default value of 0. This is what caused the need for the additional functions in the first version. While the compiler may occasionally complain (sometimes it shows the message and other times it does not), it still compiles and works.

Will be committing these to the repository on Google code sometime today.

Posted by Posted by Jeremy Wischusen under Filed under ActionScript 2, ActionScript 3, OOP, Open Source Projects Comments No Comments »

08th Aug 2008

An Eventful Revision

I finally got some time to play with my AnimatedClip class. I had a few ideas I wanted to try out. While playing with it, I realized that there was no real way to respond to tween events as all of the tweens resided in private instance variables. So I went back and added getter methods for the tween that I though people might like to respond to. So now you can do something like this:

//ball has com.vfd.animation.AnimatedClip linked to it via the library linkage.

import fl.transitions.easing.*;
import fl.transitions.TweenEvent;
ball.easing= Bounce.easeInOut;
ball.sizeTo(300,300,5);
ball.widthTween.addEventListener(TweenEvent.MOTION_FINISH, motionFinished);
function motionFinished(evt:TweenEvent) {
ball.widthTween.yoyo();
ball.heightTween.yoyo();
}

Will add this into the repository when I get home. I am mostly working on the AS3 version at this point.

Posted by Posted by Jeremy Wischusen under Filed under ActionScript 3, Open Source Projects Comments No Comments »

14th May 2008

AS 3 Animated Clip Class

So recently I finished (as in have something usable, they’re never finished) an AS3 animation class.

Basically I client of mine had me use mc_tween.as for a few projects and I decide to have a go at creating something similar in AS3 (from what I have read on the author’s site, he to is working on an AS3 version).

If you want to check out the class, you can find it on google code. Again, all of this stuff is a work in progress, so bugs are par for the course.

Here is a quick sample of how it can be used. The following example is created using this code:

//ball is a movie clip whose class I have set in the linkage dialog to com.vfd.animation.AnimatedClip;
import fl.transitions.easing.*
ball.easing = Bounce.easeInOut
ball.fadeTo(0,2, true);
ball.sizeTo(10,10, 2, true);
ball.spinTo(90, 2, true)
ball.orbitDistance = 50;
ball.startOrbit();

UPDATE:

Also started an AS 2 version. In the same code repository on google code.

Posted by Posted by Jeremy Wischusen under Filed under ActionScript 3, OOP, Open Source Projects Comments No Comments »

28th Mar 2008

Open Source Projects on Google Code

One of the IDEs that I use on a regular basis (FlashDevelop) has a repository of plugins on Google code so I started checking out the site. After looking around a bit, I figured why not. So I started two projects.

PHPageFactory:
For my day job I use a PHP framework called Framewerk. This is a very powerful system, but it is a bit more than I need for some of the other sites that I work on the side. So out of a mix of curiosity and utility, I decided I would take a shot at creating my own simple framework that more suited my needs (and just to see if I could do). The beginnings of this can be found here.

OOAS (Object Oriented ActionScript):
As mentioned in my Introduction post, I spend some of my free time answering questions at Flashkit’s forum. Eventually a discussion about OOP in ActionScript arose on the forum and I decided to do a few tutorials there. The tutorials got a pretty good response so I decided to expand on the idea and create a repository of classes I have created that is open to the general public.

Both of these are in their early stages, but I am already making modifications to the systems as I play with them. As of the time of this post, I am the only member, but we shall see how they go.

Bye for now.

Posted by Posted by Jeremy Wischusen under Filed under Open Source Projects Comments No Comments »