Search code examples
actionscript-3actionscript

Actionscript: Very slow movieclip


I am drawing a circular line to varying degrees. I wish the animation to last about 0.5 seconds. For reasons I can not work out its running very slowly.

What is weird is that if I skip the tween and call the function tweenToNext it renders instantly.

        var degrees:int;
        var posX:int = 102;
        var posY:int = 102;
        var rad:int = 100;
        var mc:MovieClip = new MovieClip();
        addChild(mc);

        mc.graphics.lineStyle(5, 0xFF0000, 1);
        mc.graphics.moveTo(posX, posY - rad)
        mc.i = -Math.PI / 2;

        tweenToNext();

        function tweenToNext(per:Number = 360):void {

            degrees += 1;

            if (mc.i <= (3 * Math.PI / 2) && degrees < per) {

                var x:Number = posX + Math.cos(mc.i) * rad;
                var y:Number = posY + Math.sin(mc.i) * rad;

                mc.graphics.lineTo(x, y); 
                mc.i += Math.PI / 180;

                TweenLite.to(mc, 0.001, {onComplete:tweenToNext});
            }

        }       

I have tried Timer and setTimeout but these produce the same slow speed.


Solution

  • Flash application runs on frame-to-frame basis: frame render - script execution - frame render - script execution - frame render - script execution - and so on. That also means that whatever smallest delay you're putting there, the next call will not happen before next script execution phase, basically, next frame. Thus - guess what - your circle drawing takes 360 frames. 12 seconds if you have 30 FPS, for example.

    If you want to make something synchronize with the real time, you need a different approach. I didn't check if this works, but I hope you'll get the idea and fix the mistakes if any.

    var degrees:int;
    
    var posX:int = 102;
    var posY:int = 102;
    
    var rad:int = 100;
    
    var mc:MovieClip = new MovieClip;
    
    addChild(mc);
    
    mc.graphics.lineStyle(5, 0xFF0000, 1);
    mc.graphics.moveTo(posX, posY + rad);
    
    // Now, magic time.
    // Save time since app start (in milliseconds).
    var startTime:int = getTimer();
    
    // 1000 milliseconds = 1 second.
    var drawingTime:int = 1000;
    
    // Store the maximum degree to draw.
    var degreeLimit:int = 360;
    
    // Call it every frame.
    mc.addEventListener(Event.ENTER_FRAME, onDraw);
    
    function onDraw(e:Event):void
    {
        // Now we need to check how much time passes since last frame
        // and update the drawing accordingly.
        var timeProgress:Number = (getTimer() - startTime) / drawingTime;
        var drawingProgress:Number = degrees / degreeLimit;
    
        // When the drawing progress catches the time progress
        // the loop will end. It will resume on the next frame.
        while (drawingProgress < timeProgress)
        {
            degrees += 1;
    
            // It's better than a property on target canvas,
            // which could be Sprite or Shape, they wouldn't take random fields.
            var anAngle:Number = degrees * Math.PI / 180;
    
            var tox:Number = posX + Math.cos(anAngle) * rad;
            var toy:Number = posY + Math.sin(anAngle) * rad;
    
            mc.graphics.lineTo(tox, toy);
    
            // We should know when to stop it.
            if (dergees >= degreeLimit)
            {
                mc.removeEventListener(Event.ENTER_FRAME);
                return;
            }
    
            // Update the drawing progress.
            drawingProgress:Number = degrees / degreeLimit;
        }
    }