Question

i'm attempting (so far unsuccessfully) to programatically increase and decrease the scale of an object on stage. there is a Grow button (grow_btn) and a Shrink button (shrink_btn), which increase and decrease the scaleX and scaleY properties of a selected object (either redObject, greenObject or blueObject) over time.

the problem i'm encountering seems random, where sometimes only one of the properties (either scaleX or scaleY) will change while the other does not. additionally, the target and original sizes for the tween functions don't adjust correctly. For example: 1.0 is nearly twice as large as the object onstage.

//Imports
import fl.transitions.Tween;
import fl.transitions.easing.*;

//Constants And Variables
const starRotationAngle:Number = 0.5;
const starSpeed:Number = 2;

var moveForward:Boolean = true;
var selectedObject:MovieClip;

//Event Listeners & Functions
star_mc.addEventListener(MouseEvent.CLICK, rotateStar);
function rotateStar(e:MouseEvent):void
    {
    star_mc.rotation += 5;
    }

addEventListener(Event.ENTER_FRAME, starMove);
function starMove(e:Event):void
    {
    if (star_mc.x >= stage.stageWidth + star_mc.width)
        {moveForward = false;}
    else if (star_mc.x <= stage.x - star_mc.width)
        {moveForward = true;}

    if (moveForward == true)
        {
        star_mc.x += starSpeed;
        star_mc.rotation += starRotationAngle;
        }       
        else
        {
        star_mc.x -= starSpeed;
        star_mc.rotation -= starRotationAngle;
        }   
    }

redObject.addEventListener(MouseEvent.CLICK, changeSelectedObjectVariable);
greenObject.addEventListener(MouseEvent.CLICK, changeSelectedObjectVariable);
blueObject.addEventListener(MouseEvent.CLICK, changeSelectedObjectVariable);
function changeSelectedObjectVariable(e:MouseEvent):void
    {
    selectedObject = e.currentTarget as MovieClip;
    }

grow_btn.addEventListener(MouseEvent.CLICK, grow);
function grow(e:MouseEvent):void
    {
    var tweenGrowX:Tween = new Tween(selectedObject, "scaleX", None.easeIn, 1.0, 2.0, 3.0, true);
    var tweenGrowY:Tween = new Tween(selectedObject, "scaleY", None.easeIn, 1.0, 2.0, 3.0, true);
    }

shrink_btn.addEventListener(MouseEvent.CLICK, shrink);
function shrink(e:MouseEvent):void
    {
    var tweenShrinkX:Tween = new Tween(selectedObject, "scaleX", None.easeIn, 2.0, 1.0, 3.0, true);
    var tweenShrinkY:Tween = new Tween(selectedObject, "scaleY", None.easeIn, 2.0, 1.0, 3.0, true);
    }
Was it helpful?

Solution

Move the tween objects outside of the listener functions, and don't use different tween objects for both grow() and shrink(). I think your problem is that you are not destroying a previous tween before applying a new tween so they are stepping on each other.

var tweenScaleX:Tween;
var tweenScaleY:Tween;

Your grow() and shrink() methods should both use these two tween variables instead of creating tween variables within the method (which makes them available for garbage collection when the function has completed even if the tween has not completed). When you call grow(), tweenScaleX and tweenScaleY are both assigned new tween objects. If the shrink button is clicked before grow() is finished, the shrink() method will begin and the tweens assigned during grow() will essentially be "destroyed" to make way for the new shrink tweens.

Furthermore, your problem might be related to AS3's garbage collection. The first answer provided said that the code works fine, but garbage collection is different from computer to computer due to performance and memory availability. A memory intensive Flash app will perform garbage collection more frequently, but on a box with lots of memory and performance it may not happen at all. As I mentioned above, since you are creating the tween variables inside the grow() and shrink() functions, their scope is only within that function. When the function completes, the variables created inside the function become eligible for garbage collection. Your tween objects will be destroyed if garbage collection occurs even if those tweens have not finished their tweens (and the "complete" event will never fire). By moving the tween variables outside of the functions in your example (or making them class members in a class), you are moving the scope to the parent object so the tween will exist as long as that parent exists. The changes to garbage collection are one of the most important but probably least understood changes from AS2 to AS3. As a developer, you might have a lot of RAM so garbage collection is not frequent (or non-existent as long as there's enough memory to hold everything), but in production your users might experience strange behavior as items are garbage collected to free up RAM but those items are referenced elsewhere since you thought they still existed and the code works fine for you. This is one complaint you see from AS3 developers a lot where they blame Adobe for making changes that cause Flash to no longer be platform independent, but it's an important feature that needed to be added to make Flash more robust.

OTHER TIPS

your code is correct. Works as it should. Check in the ide the scale of your movieclips in the transform panel, they should be set to 100 100.

Do not declare the tween objects inside the functions, they get cleaned by CG before the end of tweening. Declare them globally.

INCORRECT:

function grow(e:MouseEvent):void
{
    var tweenGrowX:Tween = new Tween(selectedObject, "scaleX", None.easeIn, 1.0, 2.0, 3.0, true);
    var tweenGrowY:Tween = new Tween(selectedObject, "scaleY", None.easeIn, 1.0, 2.0, 3.0, true);
}

CORRECT:

var tweenGrowX:Tween;
var tweenGrowY:Tween;
function grow(e:MouseEvent):void
{
    tweenGrowX = new Tween(selectedObject, "scaleX", None.easeIn, 1.0, 2.0, 3.0, true);
    tweenGrowY = new Tween(selectedObject, "scaleY", None.easeIn, 1.0, 2.0, 3.0, true);
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top