Archive for September, 2008

12th Sep 2008

Comparing Flex Frameworks

Yesterday I attended a meeting of the local Flex user group. The subject was comparing Flex frameworks presented by Yakov Fain. You can view the slides from the presentation here.

I myself have never used one of these frameworks, as I simply have never had the need for one. However I have been researching them and after attending this presentation I still feel that my initial inclination towards them stands; they exist mostly for standardization when working in teams.

By this I mean you can accomplish the same thing you can with the framework using standard Flex code and ActionScript, more than likely in a much simpler fashion depending on the project. What they afford you when working in a team is that you know that if everyone is using the same framework, then they are coding in the same fashion, hence the code written by one team member should work with the code by another. And as Yakov pointed out, they allow you to spilt up large projects among a team.

This is a nice benefit, but these benefits often come at a cost. For example one of the major complaints about Cairngorm is that you have to write a lot of classes. One reason for this is that in Cairngorm each event that the application triggers has to have a corresponding Command class. That’s a class for every event (its actually worse than that as there are other classes that these need to communicate with that you need to write as well). For a large application with a lot of events, this quickly becomes a lot of code.

Another implication of this is that you can only have one event responder per event. In other words, you lose the benefit of being able to have multiple responders to a single event that is built into Flex events, which as far as I am concerned was a great improvement over the AS2 model. Cairngorm essentially takes you back to the AS2 model.

Mate has a better event model and it does do a nice job of managing dependencies via dependency injection, but you have to maintain an event map and Mate is an MXML only framework.

And as far as PureMVC goes (look at the flow diagram slide for it in the presentation I linked to) all I can say is ???????. In its defense, PureMVC was designed to be language agnostic, but it seems to suffer from the “trying to be everything to everyone” syndrome.

The slides I linked to do a good job of pointing out the strengths and weaknesses of each framework, so I will refer you to them if you are interested in learning more.

So for now, it seems that these frameworks would get in the way more than they would simplify anything for me.

Posted by Posted by Jeremy Wischusen under Filed under Flex, OOP Comments No Comments »

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 »