« New Resolutions for 2006 | Main | Microsoft Expression CTP available. »

Dynamic frame rates for Flash animators.

Unlike a number of other applications, you cannot change the frame rate of a Flash swf at runtime. You can only set the frame rate of the whole swf at author time.

Well, that is except if you read this entry, because I'll show you an easy way (which I call framerate pumping) to change the frame rate of any movie clip in your swf so that each of them can run at a different framerate if you want!

Flash has a useful timed event handler for ActionScripters, setInterval(). This allows you to run a script periodically at a defined time period. That’s not the same as having a timeline that runs at a user defined frame rate, but you can create a setInterval() event handler that forces a timeline to run at a user defined speed. This means that you can vary the frame rate of each movie clip at runtime. You can even do it to the root timeline.

This is way cool for animators because it allows them to create more expressive animations. You can even add that ‘go fast for a split second and then slow down’ effect they use a lot in the Matrix (and any number of other films since) to create tension and/or make key moments in the action stand out.

A speeded up timeline is easy to create. Try this:

In a new fla using the default frame rate (12fps), create a tween animation inside a movie clip (such as a motion tween moving a simple circle symbol left ro right). Test your movie. Nothing unusual so far.

On the first frame of the movie clip, add the following code:

function timelineFaster() {
  nextFrame();
  updateAfterEvent();
}
var tweenFaster:Number = setInterval(timelineFaster, 1);

When you test this movie, the code will force the timeline to run as fast as it can. The script is actually telling Flash to move to the next frame every 1ms, or 1000fps. Flash can’t get that fast, so the timeline goes as fast as it can (typically 40-70fps).

To run at a movie clip at a more sensible speed such as twice the frame rate, substitute the 1 in the last line to 1/24s, (which equals 42ms).

var tweenFaster:Number = setInterval(timelineFaster, 42);

This makes the timeline go twice as fast as the normal frame rate (24fps as opposed to 12fps).

To undo the frame rate change, add the following line on the keyframe you want normal framerates:

clearInterval(tweenFaster);

If you want the timeline to continue playing from this keyframe, also add a play().

The 'scripters out there will of course see that its pretty easy to create a new movie clip class that has a frame rate property (or you can use prototypes to change the MovieClip class directly) but I don’t really think that’s necessary - most of your movie clips will run at the standard frame rate, and you will only want one or two to run faster/slower.


Posted by motiongraphics on January 14, 2006 11:14 PM

Comments
Comment by Richard

I experimented with something similar to this in the past, and found that it caused problems if there was streaming audio in the file. The audio would hiccup, etc. Did you encounter this with the above?

Posted on January 17, 2006 04:16 PM

Comment by ShamB

Yeah, it will do that because the streaming audio will try to keep up with the speeded up frame rate (if you are actually speeding up _root) or will break up the sound due to performance issues (if you are speeding up other timelines).

It's important not to overload the Flash player and use this effect minimally if you want sound to act normally (I kind of hint at this in the last para where I say this effect would typically be used for one or two clips, simply because overuse would overload the player and slow other things down).


Another thing is that streaming sounds usually imply a free running timeline, and using *any* kind of scripted jumping can break the streaming.

I'd be tempted therefore to only use speeded up or slowed down timelines where there is no sound on the timelines (or if you must have sound, use a 'speed up/slow down' background noise that is an event sound.

S

Posted on January 17, 2006 04:53 PM

Comment by oviyan

hi
can u help me that how can i add (create) keyframe in flash at runtime


oviyan

Posted on February 25, 2006 12:16 PM

Comment by ShamB

Hi Oviyan

You cannot create keyframes at runtime, but then you dont need to. What you should do instead is attach movie clips using attachMovie, createEmptyMovieClip, etc.

Posted on February 27, 2006 09:24 PM

Comment by Magoo

So I'm new to this whole action script thing but this seems like a very useful tool because I would like to be able to control the frame rate. O by the way when I said I was new to action script that was probably an understatement. What would help me the most is a step by step explanation of how to do this.

Posted on March 4, 2006 04:41 AM

Comment by eys

what if you want to go "half" the speed...

so you want the scene to run slower rather than faster... what would be the numbers to input?

Posted on May 21, 2006 06:54 PM

Comment by ShamB

Hi Eys

Assuming an original frame rate of 12 fps, your new frame rate will be 6fps or 1/6. 1/6 is 0.1667 seconds or 166.7 ms. Rounding this to 167, we can use this number as follows:

var tweenFaster:Number = setInterval(timelineFaster, 167);

Posted on May 22, 2006 12:24 PM

Comment by Jason

Ok, here's what I want to do. (by the way, your script works great, tested out took me 30 seconds to do it). i want visitors to be able to input how fast they want the movie to play. I was thinking there would be a way to do this by setting the # to a variable instead. A variable that the user controls. It sounds like it would work doesn't it? The jury is out in my head. And even if it would work, I have no idea how to do variables in flash--total novice here! but i learned everything else in flash by myself, so if you give me a few steps i should be able to figure it out. Thanks for posting this trick and I hope you can help me out with this.

Posted on June 30, 2006 01:05 PM

Comment by Miles

I have a slide presentation with many very short movie clips, many nested within other clips. I would like to slow all my movie clips down to a user-selected speed. From my experimentation with your clever code, it looks like I have to call this function from every movie clip timeline. You mention a new movie clip class. Is that something easy to explain how to do? Thanks.

Posted on July 24, 2006 01:25 PM

Comment by Luke

Thank you, it was very helpful

Posted on August 15, 2006 03:43 PM

Comment by Ids

Hello. Since I can't see your answers on the questions of the former posters (like Luke and Miles), I wanted to ask you just about the same:
I want users of my program, a musicmaker, to be able to edit the bpm (beats per minute) by pushing buttons to slow or speedup the framerate. do you know how I could do that? Thanks.

Posted on August 29, 2006 08:53 PM

Comment by ShamB

Hi Ids.

This should answer all the questions above...

If you want to create the frame rate effect for all your movie clips, add the following code as the first thing in your fla (copy/paste this into the actions panel then click auto-format to get the correct indentations):



function setFrameRate(frameRate:Number):Void {
var timelineFaster:Function = function () {
me.nextFrame();
updateAfterEvent();
};
var me:MovieClip = this;
clearInterval(me.tweenFaster);
me.tweenFaster = setInterval(timelineFaster, frameRate);
}
MovieClip.prototype.setFrameRate = setFrameRate;
MovieClip.prototype.tweenFaster = new Number();

You will now have a new method, MovieClip.setFrameRate().

Assume you have three movie clips, ball1, ball2, and ball3, each of which contains a tween that moves a ball graphic fom the left of the screen to the right, and you have added the following code after the script above (i.e. on a later keyframe or below it):



ball1.setFrameRate(1);
ball2.setFrameRate(200);

The new lines will:

move ball1 as fast as Flash can redraw it,

move ball2 every 200ms (or 1000/200 = 5fps)

move ball3 at the normal frame rate (as its frame rate is unchanged).

This effect of course has a caveat in that it will mess up your sound if overused; if you make everything faster, you overload the flash player. Put another way, this effect is really there to redistribute the peformance - if you make something faster, you have to make something else slower!

Hope that helps everyone.

Posted on August 30, 2006 11:50 AM

Comment by ShamB

Before anyone asks, here's the non-typed code for Flash 6 users....

function setFrameRate(frameRate) {
	var timelineFaster = function () {
		me.nextFrame();
		updateAfterEvent();
	};
	var me = this;
	clearInterval(this.tweenFaster);
	this.tweenFaster = setInterval(timelineFaster, frameRate);
}
MovieClip.prototype.setFrameRate = setFrameRate;
MovieClip.prototype.tweenFaster = new Number();
//
//
ball1.setFrameRate(1);
ball2.setFrameRate(200);

Assuming you have the three movie clips (ball1, ball2, ball3) on the stage, just copy/paste the code above into a new layer called actions.

Posted on August 30, 2006 12:11 PM

Comment by Shamb

I've just found that some people will have difficulty copy-pasting the code into Flash because of the HTML tags, so I've put flash 6 and Flash 7 flas of the example up here

Posted on August 30, 2006 12:24 PM

Comment by jdr

Hi,

I tried the mc interval code you have posted. (I want to run the mc at a slower speed that my main movie)

I put it in the first frame of my mc and cleared it on last frame.

It works (kinda), but it seems to slow the entire movie down from point of exectution, plus at my movie end, I have a "replay" button which play the movie again from frame one...and now the effect seems to be cumlative - it's twice as slow.

I'm a Flash "designer" so my actionscript knowledge is limited (I try though).

Can you suggest a solution?

Thanks,

John

Posted on November 16, 2006 01:20 PM

Comment by tony

would you be able to make a movie clip where the frame rate would gradually decrease to a stop? i'm assuming it would, you'd just have to change the framerate at the right points to create the illusion of slowing down?

Posted on December 3, 2006 11:45 PM

Comment by Kenny

I tried this in a preloader in scene one of a two scene movie.

Although I cleared the interval as directed (at the last frame of scene 1 and then at the start of frame 2 as a second fix) the code somehow managed to cause the movie to ignore all 'stop' scripting in any frames, so it just ran through my 2nd movie and that was the end of my presentation!

A great bit if scripting but the side effects cause it to be useless.

Posted on February 18, 2007 08:45 PM

Comment by Todd

I can see that this has not been posted on for a long time so I'm hoping someone will still see my post. Well i had a question about this script. I am creating a flash guitar tutorial with 3d animations in it for class. What I would like to do is put a slider in the flash file so that the user can adjust the speed of my animations. For example for one portion of the tutorial there is a 3d animation of a guitarist playing a scale. I want the user to be able to speed up or slow down the clip so they can play along at a speed they are comfortable with. Can I make this work with a slider and if so how do I do it? There is sound with the animations as well so I will probably run into problems with that as well.

Thanks
Todd
email
toddk6444@hotmail.com

Posted on February 27, 2007 01:49 AM

Comment by briston

nice tut.

i wanted my movie to loop at a slower framerate so i did the following:

function timelineFaster() {

_root.movie_right.video_inside.gotoAndPlay(_currentFrame + 1);

updateAfterEvent();

}

var tweenFaster:Number = setInterval(timelineFaster, 32);

Posted on June 1, 2007 12:52 AM

Comment by Vent

Will this actionscript work on speeding up graphic symbols? Or just movie clips? Because I rarely use movie clips because I export to avi a lot. Thanks!

Posted on June 28, 2007 10:48 PM

Comment by Zendemic

Nice straightforward tute, cheers!

Posted on June 29, 2007 05:44 AM

Comment by jk-mc

thank you shamB, i was looking for that for a few hours, appreciate the help.

Posted on July 24, 2007 02:48 PM

Comment by Sangram

Hi,i am creating yahoo search application component in AS 2.0. In that component i want to display results in multiple pages. Can you tell me some idea for this . For eg. how to divide the result in multiple pages

Posted on August 6, 2007 01:04 PM

Comment by Sangram

Hi,i am creating yahoo search application component in AS 2.0. In that component i want to display results in multiple pages. Can you tell me some idea for this . For eg. how to divide the result in multiple pages

Thanks & Regards,
Sangram.

Posted on August 6, 2007 01:05 PM

Comment by Cobretti

Can you solve sound problem?

Posted on December 3, 2007 07:45 PM

Comment by Monica

I have a question. I am creating a game in which I am setting up a movie clip in the shape of a bar with a dot moving back and forth; this will serve as my aiming bar for a target that will cause another movie clip to "fall" into water if hit (I'm creating a virtual dunking booth). My question is this: I want to set up three different levels - an easy one where the dot on the bar moves slower, therefore making it easy to hit the target; a medium level where the dot on the bar moves a little faster, making it harder to hit the target; and a difficult level where the dot on the bar moves fast, making it the most difficult to hit the target. I understand how I can change the framerate dynamically, but when I entered the code you posted in this article/post to change the frame rate in my movie clip, my movie clip no longer looped. What code do I need to add to force the movie clip to continue to loop? This is probably an easy fix, but I am quite new to flash and actionscript, and I am not a programmer.

Thanks!

Monica

Posted on December 8, 2007 01:45 AM

Comment by Monica

I have a question. I am creating a game in which I am setting up a movie clip in the shape of a bar with a dot moving back and forth; this will serve as my aiming bar for a target that will cause another movie clip to "fall" into water if hit (I'm creating a virtual dunking booth). My question is this: I want to set up three different levels - an easy one where the dot on the bar moves slower, therefore making it easy to hit the target; a medium level where the dot on the bar moves a little faster, making it harder to hit the target; and a difficult level where the dot on the bar moves fast, making it the most difficult to hit the target. I understand how I can change the framerate dynamically, but when I entered the code you posted in this article/post to change the frame rate in my movie clip, my movie clip no longer looped. What code do I need to add to force the movie clip to continue to loop? This is probably an easy fix, but I am quite new to flash and actionscript, and I am not a programmer.

Thanks!

Monica

Posted on December 8, 2007 01:46 AM

Post a comment




Remember Me?

(you may use HTML tags for style)