ENTER FRAME vs Timer

11 posts

Flag Post

Hi all

I’m new to AS3 programming, now i’m using ENTER_FRAME event to make my games, but i’m wondering what is the best way to do it. also i saw some examples using Time but i’m not very convinced.

another question is how to achieve framerate independence?

cheers

 
Flag Post

What I do, and I think its a pretty solid implementation, is to have only one object that actually subscribes to the ENTER_FRAME event. I then, using a whole lot of object oriented style subclassing and such, have all my objects that need to be updated every frame updated by that one main subscriber. This way, flash tells me when a new frame has been started, and then I’m in total control of how every one of my objects updates.

Then you really want to use a delta time (dt) variable and send it to each of your objects. This may seem confusing to newbies (it certainly was for me) but it is very important that your object knows how much time has passed since the last frame update. This way, if I have a ball that’s supposed to move across the entire screen in 10 seconds, it will always take 10 seconds to move across the screen. If I didnt use dt for my calculations and just moved the ball a set amount each frame, then if the game was running at 100 FPS the ball would get across the screen 10 times faster than if the simulation ran at 10 FPS.

A lot of people will say timers are inaccurate, but over the small amount of time between two frame updates using the getTimer() command is fairly accurate, and what I do is in my root ENTER_FRAME subscriber I have a variable that keeps track of how much time has passed since the game started on the previous frame and subtract that from the result of getTimer(). The result of that is how much time has passed since the last frame update, which is our delta time variable (dt). This is in milliseconds and would be about 33 if we run at 30 FPS.

Ok, now this seems like it should be enough, but if you wanna do acceleration and physics, it isn’t. In actuality, the lower your framerate, the larger your delta time variable will be and, since all our acceleration calculations are really just approximations, the more inaccurate movement and stuff is. If you don’t try to do acceleration or physics in your game and all movement is at a static speed, then you should be fine, but if you are you have to do one more step. This is where my method of having only one head object be in control of frame updates really pays off. All you really have to do to keep acceleration calculations consistent is to ensure dt is the same every time you update. I do this by setting dt to 10ms for every update, and then the amount of time that passed since the last frame is decreased within a loop until it is less than 10. Each pass of that loop updates all my objects with a dt of 10. Its super simple, and it works great.

That may have been tough to swallow, so here’s the code to go with.


public static function frameUpdate(event:Event)
{
mAccumulator += (getTimer() – mTime) * GameData.SpeedMult; //this accumulator gets the time passed since last update
var deltaTime:uint = 10; //my static delta time
mTime = getTimer(); //get the current time on THIS frame

while(mAccumulator >= deltaTime) //the update loop, runs until we’ve “caught up”
{
for(var iter:uint = 0; iter < mSubscribers.length; iter++)
{
mSubscribers[iter].tick(deltaTime); //here i tick all my objects
}
mAccumulator -= deltaTime;
}
//trace(“framewatcher now done ticking all objects. see you next time!”);
}

 
Flag Post

@fucrate: Thanks for your reply, i appreciate it. i will study the second part sounds interesting.

regards

 
Flag Post

If you wanna do physics stuff and want to see a more in depth explanation of how to fix your timestep, check out gaffers blog

its super in-depth and i’ve followed a lot of his advice except for using RK4 integration because i think it’d be pretty slow in flash (but mostly because i’m lazy).

 
Flag Post

Hi,

Thanks fucrate for your excellent input. I do however have some criticism of your post at the end.

I’d like to provide some additional information to ekagauranga and all others interested in simulation-style game development.

As explained by fucrate, deltatime is the jump in time that occurs between 2 consecutive frames. Because of this jump, the science of simulation is based on discrete-math and numerical analysis. If we are to assume that deltatime is almost zero, then we can readily apply our high-school/college physics in really cool ways. For example, if you know some calculus, you are probably aware that:

[edit: math fixed]
a = dv/dt. (v is velocity, a is acceleration, t is time, da means delta-acceleration which means ‘change in acceleration’)
Similarly,
v = dp/dt. (p is position)

And guess what, the dt in those formulas, can be replaced by the deltaTime calculation shown by fucrate (I’ll be showing a nicer method later). I will now rearrange the formula for position as an example:
v = (new_p – old_p)/dt; // (dv = change in velocity)
new_p – old_p = v * dt;
thus: new_p = old_p + v * dt;
p += v * dt; // QED

As such, you can make a really cool space game for example, where given some force or acceleration, you can derive its position in the following way:
a = F/m; (F is Force and m is mass, if you want to be really anal)
v += a * dt/1000; // (the * 1000 comes from the fact that dt is in milliseconds)
p += v * dt/1000;

And thats it :). This way you get fps-independent, realistic physics motion. How come? If you think about, when the FPS is really high, then dt will be very small, and since from the equation that means that the velocity and position will change by a lesser amount. This makes sense because on a fast computer, more frames are invoked so the change in distance at each frame should be smaller. Similarly when the FPS (frames per second btw) is low, then dt is high making the jump in distance and speed higher, thus resulting in the same distance covered over the same amount of time. btw, C freaks that prefer performance over accuracy could rewrite this formula to be v += a * dt>>10 but I wouldn’t recommend it cuz you will lose some additional accuracy (wont work in Flash anyways).

Ofcourse, dt is NOT zero, so it will not be totally accurate, but will be close enough for games. However, if you are modelling the solar system for example with planets rotating, you may need some manual correction. The above is a variation of Eulors method. If you want greater accuracy, try Eulors ODEs (Ordinary Differential Equations), to be able to predict discrete events and take them into account. For example, frame 1, ball is above ground (falling downward), frame 2, ball is partially gone through the ground. You then use ODE’s to find the point of intersection and extrapolate the correct new position of the ball above the ground. If you want to go really crazy, try Runga Kutta, and you can accurately model even atoms!

Now I present a significantly easier calculation of dt which will work just fine:

deltaTime = getTimer() – lastTime;
lastTime = getTimer();

Voila! Much easier huh? Also, fucrates method is not something performance-intensive game developers will want to use. It contains a loop that will be done every single frame, all to satisfy the redundant requirement that dt should be “the same every time you update”. This is actually bad and you should not do that. If games did that, there would be no such thing as an FPS, because it would be the constant all the time.

fucrates talked about using Polymorphism, which is very useful. Do try to use polymorphism for performing such functions. As an example, you may have the following structure (written in C++/UML form):

NewtonianClass
+ virtual void doFrameMath() { v += a * dt/1000; p += v * dt/1000; }
+ virtual void doFrame() = 0;

  1. Vector3& F, a, v, p; // Vector3 for 3D games, Vector2 for 2D games

AllOtherObjects : NewtonianClass
+ virtual void doFrame() { doFrameMath(); DO OBJECT PER-FRAME STUFF; }

Now you can have an array that holds all your objects as a NewtonianClass, and just have:
for (var n : NewtonianClass in objectArray) {
n.doFrame();
}

And just these 2 lines will automatically do the physics for all the objects.

I would also like to clear a certain misunderstanding. A lot of people say timers are inaccurate, true, but the statement that “over the small amount of time… the getTimer() command is fairly accurate”. This is actually incorrect. The “lot of people” got it right. In fact, the longer the duration, the more relatively accurate it is. The precision of a timer is what defines its’ accuracy. The getTimer() method in Flash has a precision of about 10ms, which means that it is accurate to the nearest 10th millisecond. If you are a C++ programmer, then you have access to the more higher resolution timers on a system, however these timers are computer-architecture dependant and their api are operating-system dependant. On Windows, you can use the QueryPerformanceCounter for a high-resolution timer, which will give a count of the clock cycles of your cpu. getTimer() however is a low-resolution timer, and thus, when deltaTime is very small, its’ relative accuracy is actually much lower.

WARNING:
Although the method shown here is crucial for many games, especially multiplayer games, it does have its problems. The main problem is that if for some reason the computer freezes for a few seconds, then deltaTime is growing, resulting in a sudden jerk in motion to make objects appear where they should have appeared had they carried on their motion. This is a good and bad thing. The bad of it is that it can mess up your assumptions. This is exactly the effect we call lag in online games.

 
Flag Post

Salman:

Your math is wrong (can’t tell if this screws up your coding entirely, or at all, I’ll leave that to you).

You state:
*****************
v = da/dt. (v is velocity, a is acceleration, t is time, da means delta-acceleration which means ‘change in acceleration’)
Similarly,
p = dv/dt. (p is position)
*******************

Both incorrect (you have the “hierarchy”, so to speak, upside down

if p = position, then
v = dp / dt (velocity is a change in the position, over a period of time, and)
a = dv / dt (an accel is a change in velocity, over time)

then (I will also omit the proof, but it is very easy to do)

new_p = old_p + v*t + 1/2 * a * t squared (what you would find in a calculus book)

and assuming uniform motion (no acceleration):

new_p = old_p + v*t

quick logic-test: if your object moves at a given speed “v”, for twice the time “t”, the position would change twice as much, right? Thus, “t” needs to be multiplied, not divided by.

 
Flag Post

lol.

Whoops. You’re right; I accidently wrote p = dv/dt when it should be v = dp/dt and a = dv/dt. Big boo boo. And yes ofcourse that makes the Math wrong. I’ve fixed it in the original now. You need to do the following in your code:

v += a * dt/1000;
p += v * dt/1000;

Ofcourse, I treat p, a and v as vectors, so you’ll have to do stuff like
v.x += a.x * dt/1000;
v.y += a.y * dt/1000;
p.x += v.x * dt/1000;
p.y += v.x * dt/1000;

Or you could create a Class called Vector2 and overload the + and * operators (dunno if u could do that in AS3).

Sorry about that. The equation you provided is correct, but for small deltaTimes this method is much faster, and is accurate. Also, the equation you provided, i.e s = ut + 0.5at2 works great when you base your code on the actual result of getTime() or some concept of time elapsed. This can be useful when doing some fixed animation, but for games where there are dynamic events, its better to deal with dt than timeElapsed.

 
Flag Post

I’d just like to respond to salman about the loop in my tick() function. While it’s true that it slows performance a bit, the real performance drain in my code and I assume most other people’s code is not the ticking function but the actual display of objects to the screen that flash handles internally.

That said, the reality of the loop in my function is that it usually only runs a couple times unless performance is really poor, and it does a lot to increase the consistency of the physics in my simulation. I’m currently writing a porpoise game, and when I am in an area of high complexity and thus have a low framerate, my porpoise can jump twice as high as when I am in a area of low complexity when I don’t do the extra loop. This is because deltaTime varies greatly and the calculations are more inaccurate.

Also I’m using AS3, so all of my code executes pretty darn fast anyway, which helps keep the extra loop from hurting the framerate much.

It’s because of the inaccuracies that just putting dt into the mix wont be good enough if your framerate is likely to vary a lot. However, most flash games have their framerate locked at a specific rate, my target is 30, and in the end this will ensure a pretty consistent simulation without taking the performance hit my loop does cause. If someone playing your game hits a framerate significantly lower than 30, then the accuracy of the physics is gonna be the least of their problems. So by the time I start optimizing my code I may end up taking the loop out anyway :)

If you still don’t believe me, Salman, try setting your published framerate to 120 and watch your objects fly much shorter distances than when you set it to 15. With AS3 i can set my fps to 600 and everything works pretty much the same (which is sweet btw, as3 is pretty pimp).

About timers, you would be one of the aforementioned “people” who say timers are inaccurate :) Allow me to qualify my statement: timers are very accurate, as they are based on the system time. Usually it is difficult to use a timer quickly, say a 10ms timer, because when you schedule an event to a timer it takes a certain amount of time to run the event function. Usually the timer is reset at the end of the event function and, if you had to do a bunch of math, then you wasted a lot of time, which makes the use of the timer almost pointless.

What I’m doing is different because I’m just grabbing the current elapsed time since the last time i grabbed the current elapsed time which includes all the time I take to tick my objects as well as the time it took to obtain the current time. There’s nothing inaccurate about this method, but I’m not totally sure how accurate the function is in AS2.

 
Flag Post

obviously i’m super bored, so i threw together a little demo .swf to demonstrate what happens when i don’t use the accumulator and the loop to keep my simulation consistent in the face of varying framerates.

http://www.intuitiongames.com/test%20project.swf

The above links to a bunch of green balls appearing and moving off to the left, theres just a constant velocity for each and they disappear after about 50 frames or so. If you hit tilde (~) you can get the console. The commands are as follows:

fps – pulls up the fps ticker, you’ll want that

fps=X – with x being the desired framerate, you can put anything here, i think switching between 100 and 10 gives a good variance

noLoop – uses a non looping solution which just gives dt to all the physics objects

useLoop – changes it to my looping style

You’ll note that when you are in useLoop mode, no matter what framerate you’re at, the green balls move at pretty much the same rate. When you’re in noLoop mode, the lower your framerate, the slower the green balls move.

 
Flag Post

hey fucrate,

cool demo. The “system timer” itself has a maximum accuracy of 10ms. It cannot be better than that. For proof that Flash is limited by the system timer, read the following article by a blogger working at Adobe:
http://www.kaourantin.net/2006/05/frame-rates-in-flash-player.html

Now, suppose you force your fps=30, then when ur game is on slower machines, the fps may end up being 25. To make things worse, flash behaves 20% slower on a browser than the flash player. In your demo right now, when I put fps=30 i get an fps of 25 (ur cool demo certainly helps make my point! Did you try to test on a browser?). This will cause your assumptions to mess up and your game difficulty to vary significantly. Also, when high scores are reported, its not so fair because people with slower machines had more time to react.

The best technique is specify your physic properties in actual units. For example, I want my car to travel 20 pixels / second. Period. No matter how slow or fast the computer is, it should go at 20 pixels / second. Ideally, you should be saying stuff like, the car should go 0 to 60 mph in 5 seconds. Guess what, you CAN do that! You do that by placing the desired scale on the frame (in this case in miles), converting hours to second, then just multiplying that number by dt/1000 using the technique I described.

Try it; I think you’ll find the results quite interesting :).

Good luck,

Salman

 
Flag Post

just giving this topic a little bump- i started coding my first game recently and i found this extremely helpful!

btw, i have an object with a velocity that diminishes over time. before when i was timing things by frame, i simply multiplied my velocity by .99 per frame (which, at 30 fps, would diminish my speed by roughly 26% per second). but now that i’m using this time based method, the correct way to diminish my speed at the same rate would be to multiple my speed by .74^(dt/1000)… my question here is, will it slow things down significantly to have my game executing a Math.pow command with an exponent in the thousanths 30 times a second?