Multiple tweening problem

Posted on April 4, 2009


While developing a multi player poker game I got strange problems with tweening using fl.transition.Tween class. There were 18 cards to be distributed among 9 players in sequence and with 100ms interval. I put them in a timer and fired tweens at each timer event. I was writing the tweening code inside a method and adding event listeners to capture the finish event of the tween event. Problems that raised by this process were:

Problems:

1. Sometimes cards hangup while distribution.

2. Cards could not reach the exact location specified.

In other words the tween freezes on the way. 

This kind of problem arises mostly in the following cases:

1. Tweening multiple objects either synchronously or asynchronously by using local variables to handle tween events.

2. Tweening multiple properties of an object and adding event to one of them. ex:

  1. var tweenObj:Tween=new Tween(targetClip, "x",….other params…);
  2. new Tween(targetClip,"y",…..other params…);
  3. tweenObj.addEventListener(TweenEvent.MOTION_FINISH, eventHandler);

Note: I have added event listener to the tweenObj  which modifies the ‘x’ property of the targetClip.

Reason:

The first problem arises because of garbage collection of the tween objects as because they are declared as local variables(variables declared within a method). So in the way of transition/transformation the tween is dumped to garbage area and tween stops. This case is not a regular case so can not be reproducible every time(or I might not have understand it well enough the exact time after which tween object looses its status).

For the second problem when event handlers are created for the tween object that is declared first, other properties may not be able to finish their motion when MOTION_FINISH is fired by the tween object. If the object is disabled by this event, then other properties may not complete their transformations and freeze.

Solutions:

To prevent objects from garbage collection we need to declare the tween objects in some global variables and apply them inside methods. Here is the example:

  1. private var _tween:Tween;
  2.  
  3. private function createTween():void{
  4.       _tween=new Tween(clip, "x", Elastic.easeOut, 0, 300, 3, true);
  5.       _tween.addEventListener(TweenEvent.MOTION_FINISH, eventHandler);
  6. }

This solution is wise to use when you have small no of tweens. But if you have to create more no of tweens or tween that are created at run-time based on iterations, it’s not a good solution.

Using a dictionary object to reference the tween objects is often helpful to overcome the situations of tweening by iterations. And it’s easy to handle the dictionary objects for effective control in garbage collection. Here is the example:

  1. private var _tweenDC:Dictionary=new Dictionary;
  2.  
  3. private function createTween():void{
  4.       var clipXTween:Tween=new Tween(clip, "x", Elastic.easeOut, 0, 300, 3, true);
  5.        _tweenDC[clip]=clipXTween;
  6.        // if you have more than one property to tween you may use
  7.        // _tweenDC[clipXTween]=clipXTween;
  8.       clipXTween.addEventListener(TweenEvent.MOTION_FINISH, eventHandler);
  9. }
  10. // clear all the collected tweens
  11. private function eventHandler(evt:TweenEvent):void{
  12.     _tweenDC=new Dictionary;// Indeed not a good option. why?
  13.     // or you can do as follows for the second case discussed above.
  14.     // _tweenDC[evt.currentTarget]=null;
  15.     //  delete  _tweenDC[evt.currentTarget];
  16. }

Another way of handling multiple tweening by iterations is to reference the tweens by creating dynamic
properties of a movie clip which should be declared inside the class scope. This is specially for animating multiple properties of a same clip with iterations.

  1. private var _tweenCollector:MovieClip=new MovieClip;
  2.  
  3. private function createTween():void{
  4.       for(var i:int=0;i<=23; i++){
  5.           var _mc:Clip=new Clip;//clip is some custom class
  6.           addChild(_mc);
  7.           _tweenCollector["scalexn"+i]=new Tween(_mc, "scaleX", Strong.easeOut, 1, 1.3, .4, true);
  8.           _tweenCollector["scaleyn"+i]=new Tween(_mc, "scaleY", Strong.easeOut, 1, 1.3, .4, true);
  9.           _tweenCollector["xn"+i]=new Tween(_mc, "x", Strong.easeOut, 200, 280, .4, true);
  10.           _tweenCollector["yn" + i] = new Tween(_mc, "y", Strong.easeOut, 200,200, .4, true);
  11.           _tweenCollector["yn" + i].addEventListener(TweenEvent.MOTION_FINISH, eventHandler);
  12.       }
  13. }
  14. // clear all the collected tweens
  15. private function eventHandler(evt:TweenEvent):void{
  16.      _tweenCollector=new MovieClip;
  17. }

At some cases the above method may be risky, yet this concept worked fine for me in some of my projects.

Let’s see if any other good way exists.


Posted Under AS3, Flash »


Comments

One Response to “Multiple tweening problem”

  1. Gary Phifer on August 5th, 2009 6:20 am

    In my case I have a sequence of two tweens fired off concurrently along with a TransitionManager fade-in of an image. Both tweens stop short of completion on the first iteration. Strange thing is, after 2-3 iterations, it appears to correct itself.
    However, by declaring the tweens outside the function, the sequence works correctly the first time and every time thereafter.

    Thanks for the tip.

Leave a Reply