• Looking for something?

Frame Based vs Time Based using enterFrame -AS2

Ever experience sudden frame rate drop or frame boost on your game, having sudden lag spikes and performance issues, did it affect the game play tremendously like it slowed down or made everything faster. It is either you really code awfully or your game is so affected with the FPS rate changes from various browsers and the user’s machine capability.

This is where time based coding takes place. By default, most of us amateurs went and started with frame based not knowing what it really is. When we say frame based the code and/or animation is dependent solely on how fast the FPS was set to, with a steady code, reducing the FPS rate will slow down the game and increasing it will hasten it. Time based coding can manage this quite well since everything can be dependent on time so frame rate doesn’t affect it that much. This problem is not only for games but for any development.

Code:
Let’s get started, I will discuss this with the sense of OOP approach where there is only a centralized loop function called to handle everything. I will not be actually using setInterval but the usual onEnterFrame event function.
This code is assumed to be part of a class, most cases shall be used in the main engine class but can also be used inside other classes too as long as it is correctly structured. This also assumes that the buffer movieclip is already instantiated.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
static var frameSpd:Number;
var frameTime:Number;
var buffer:MovieClip;
 
function startEngine() {
	// some more codes here
	buffer.onEnterFrame = Delegate.create( this, loop );
	// some more codes here
}
function loop() {
	frameTime = ( getTimer() - frameTime ) / 1000;
	_root.fpstxt = Math.round( 10 / frameTime ) / 10 +'fps\n '+ frameTime*1000 +'ms';
	frameSpd = frameTime / 0.030;
	frameSpd = Math.min( 2.5, frameSpd );
	var t:Number = getTimer();
 
	// more and more codes are called from here
 
	frameTime  = getTimer();
	_root.fpstxt += '\n'+ ( frameTime - t ) + 'ms';
}

Lines 1: made frameSpd a static variable so it can be easily accessed from any other location or class.

Line 11 & 19: frameTime is the time difference from when the loop was last called and ended.

Line 12 & 20: returns the frame’s FPS, last frame’s difference speed and actionscript process time.

Line 13: frameSpd is a variable that determines as a multiplier based on frameTime and the default FPS rate setting (in this case I use 30 as the movie’s FPS so 30/1000 = 0.030)

Line 14: makes a tolerance on how slow the frame rate has been and how much frameSpd has to catch up.

Implementations:
I’ll write some possible implementations in a pseudo code way using AS2 syntax and assuming that Engine is the name of the class where loop is located.

For basic movements, something like this on you movement function:

1
2
3
4
5
6
7
8
9
var spd:Number = this.speed * Engine.frameSpd;
// going left
if ( dirx < 0 ) {
	_pos.x -= spd;
// going right
} else if ( dirx > 0 ) {
	_pos.x += spd;
}
// more and more code possible here

Having gravity or other accelerating factor is quite tricky but not really too complex, something like this on your affect gravity functions:

1
2
3
4
5
6
7
// store the var locally to improve lookup speed since it is used more than once
var frameSpd:Number = Engine.frameSpd
// apply gravity or any factor with acceleration
jumpspeed += Engine.gravity * frameSpd;
// apply the speed
var spd:Number = jumpspeed * frameSpd;
_pos.y += spd;

And my favorite, handling animation speed (this one is for characters usually)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
var frameSkip:Number = Main.round( 4 * Engine.frameSpd ) + 1;
// see what current frame I am on
switch( _cframe ) {
	case 1: // stand and idle
		if ( _ccframe + frameSkip > 100 ) _ccframe = ( _ccframe + frameSkip) % 100
		else _ccframe += frameSkip;
		break;
	case 3: // run
		if ( _ccframe + frameSkip > 80 ) _ccframe = ( _ccframe + frameSkip) % 80
		else _ccframe += frameSkip;
		break;
	case 5: // jump
		if ( _ccframe + frameSkip > 65 ) _ccframe = ( _ccframe + frameSkip ) % 65 + 25;
		else _ccframe += frameSkip;
	break;
	case 7: // double jump
		if ( _ccframe + frameSkip > 50 ) {
			_ccframe = ( _ccframe + frameSkip ) % 50 + 25;
			_cframe = 5;
		} else _ccframe += frameSkip;
	break;
	default: break;
}

_cframe is the current animation frame of the character and _ccframe acts like a play head for the animation itself. If you have questions about this, my animation controller is discussed well enough on this post.

So basically having time based coding is a really powerful feature, you can even force multiply the frameSpd to a certain speed either on purposely speeding up your game or making it slow motion (matrix style). From the loop code from the top most edit it with this:

1
frameSpd = Math.min( 2.5, frameSpd ) * forceSpd;

Just make sure frameSpd maintains a tolerable value; having 10 would make it intensely fast and 0.1 would make it gruesomely slow. By default it has value of 1, 2 to make it twice and 0.5 to make half the speed, same goes if you’ll use a forceSpd.


Have something about this? There are 4, where's yours?
  1. Plamen

    I don’t get it. What are you doing on line 13?
    frameSpd = frameTime / 0.030;

    Let’s say frameTime is 1 ( 1 sec ). If you divide it by 0.03 you will get 30 sec? Right? Is that what it should be ?

  2. Jayc

    If your frameTime is 1 then that would mean that it took 1 sec for the next frame to be called again (an incredible frame rate drop of 1 fps). So you get 33.33 frameSpd and have to adjust all speeds 33.33x faster to catch up everything. But the next line (14) limits that amount of catching up to 2.5, so any frameTime slower than 0.075 sec (75ms) would no longer be tolerable.

    It’s set to 0.030 because the swf is set to 33fps by default.
    33/1000 = 0.030 (well its 0.033 actually)

    So normally frameSpd would be 1 when runtime fps is the same with the default fps.

  3. Plamen

    Yeah, I get it :) I wrote everything on a paper and also made a lot of traces in the code you wrote to see different situations and results :) Good job Jayc. I really like your posts in FGL too :) . Keep going !

  4. Jayc

    Thanks plamen,

    well now that I reviewed it, the default FPS is actually 30 making 30/1000=0.03. Lol (updated the post now)

Leave a Comment


 (not published)


= Sum of 6 + 9 ? If this is your first post, your comment will be moderated.
Please use english and keep it punctual.
Pings & Trackbacks
  1. Using a Frame Controller to do animations -AS2 » Jayc Santos

    [...] This is because our frame controller must be able to tolerate slight FPS reductions based on time (detailed on ...