Vukašin Petrović
Vukašin Petrović

Reputation: 165

AS3 get smoother image rotation

I have a timer that rotates image for 2 degrees every 10 ms 1000 times. It rotates well, but sometimes (not always) I see some stuttering for just a tiny bit of time, it's not big but it is noticeable. How can I change my code to prevent that? Is there faster and better way than using "mc.rotationZ"? It might be my timer with 10ms time cycle, that causes problem?

EDIT: If timer is a problem, what are alternatives for it?

startbtn.addEventListener(MouseEvent.CLICK,okreni1);
var tajmer:Timer=new Timer(10,1000);
tajmer.addEventListener(TimerEvent.TIMER,okreni2);

function okreni1(e:Event){
    startbtn.mouseEnabled = false;
    tajmer.start();
}

function okreni2(e:Event){
    wheel.wrotate.rotationZ += 2;

    if(tajmer.currentCount == 1000){
        trace("tajmer se zavrsio");
        startbtn.mouseEnabled = true;
        tajmer.reset();
    }
}

Upvotes: 2

Views: 241

Answers (2)

Vukašin Petrović
Vukašin Petrović

Reputation: 165

Strangely, I tested my FLA (swf) on school's old pc with 1 cpu core and integrated gpu, and rotation(animation) worked flawlessly. But I think maybe the problem is in my flash professional or flash player. I will reinstall and update my software. Thank you @LMDS very much for all help.

Upvotes: 0

BadFeelingAboutThis
BadFeelingAboutThis

Reputation: 14406

  1. Could be performance (UPDATE: from your comments I'm going to say this is unlikely)
  2. Make sure if using an image, that bitmap smoothing is enabled on it and pixel snapping is off.
  3. Make sure you're publishing with GPU acceleration.
  4. Make sure you're not scaling the parent(s) of wrotate a huge amount. You can get into jerky motion when things get scaled up really far.

It's likely that the problem would be resolved if you updated the object every frame instead of on a timer event. Though it's best to do this even if it's not your main problem.

at 10ms, you're actually making changes faster than 60fps (which is 16.6ms). At flash pro's default 24fps (41.6ms) that's 4 timer ticks before your changes are drawn. Plus, timer's can't reliably sync to the frame rate even if you did the math right.

I've modified your code so that the timer only has one tick that spans the entire duration of the rotation. An enter frame listener is what handles the rotation so that it's synced with the actual frame rate of the application.

startbtn.addEventListener(MouseEvent.CLICK,okreni1);
var tajmer:Timer=new Timer(10000, 1); //just fire it once 
tajmer.addEventListener(TimerEvent.TIMER,okreni2);

function okreni1(e:Event){
    startbtn.mouseEnabled = false;
    tajmer.reset();
    tajmer.start();
    wheel.addEventListener(Event.ENTER_FRAME, updateWheel,false,0,true); //run updateWheel every frame
}

function okreni2(e:Event){
    wheel.removeEventListener(Event.ENTER_FRAME,updateWheel,false);  //remove the listener so it stops rotating
    trace("tajmer se zavrsio");
    startbtn.mouseEnabled = true;
}
function updateWheel(e:Event){
    wheel.wrotate.rotationZ += 2;
}

As an aside, this scenario is a perfect candidate for Tweening. If you wanted to use the ever popular TweenLite, your code would look like this:

import com.greensock.TweenLite;
import com.greensock.easing.Linear;
import com.greensock.easing.Quad;

startbtn.addEventListener(MouseEvent.CLICK,okreni1);

function okreni1(e:Event){
    startbtn.mouseEnabled = false;

    //this tells wheel.wrotate to animate over 10 seconds from the current rotationZ value to an additional 20000.  Ease none means have the velocity constant the whole time. 
    //alternatively you could use a different ease, like Quad.easeInOut if you want a nice smooth start and stop
    TweenLite.to(wheel.wrotate, 10, { rotationZ: wheel.wrotate.rotationZ + 20000, ease: Linear.easeNone, onComplete: okreni2 });
}

function okreni2(e:Event){
    startbtn.mouseEnabled = true;
}

Upvotes: 2

Related Questions