PDA

View Full Version : [f9] game timer techniques



robotz
January 16th, 2008, 07:06 PM
Hi all,

I just wanted to ask what people felt is the best way to achieve a constant frame rate in your AS3 games?

I've read that the frame rate (as set via stage.frameRate or the Flash IDE) is notorious for being unreliable. Are there any "best practise" methods you could point me to please?

I'm creating a simple 2D bitmap driven game, with the game sprites copyPixeled onto a screen buffer which is working fine, but appears quite inconsistent across different PCs as all I did was set the framerate in the IDE to 31.

If I swap for an internal "game timer" technique I'm curious how you'd then calculate the amount needed to be added to an existing sprite in order to get it to move say 5 pixels per second (and so all of your other game elements also work off the same "frame rate")

Help / pointers gladly received!

oldmanwinter
January 16th, 2008, 07:32 PM
since the frame rate will vary depending on the persons computer and the amount of crap going on on-screen, i've been using this technique that moves items at rates based on clock time rather then framerate.

dt=(getTimer()-ltime)/1000;
ltime=getTimer();dt (delta time) is the amount of time that's passed since the last frame was loaded, which you can then plug into the equations you use to move your characters, like this:


player._x+=dt*(velx+.5*acelx*dt);
player._y+=dt*(vely+.5*acely*dt);
velx+=acelx*dt;
vely+=acely*dt;
acelx=0;
acely=0;i just cut and pasted that code from this platforming game i'm working on. you've probably noticed that there's a little more math involved then the standard "player._x+=velx" that you can use when the passage of time is considered constant between frames. the player is moved by his velocity (in pixels per second) times dt plus half the players aceleration times dt squared (something they teach you in the second week of a physics course). the acel is kind of important if you have a velocity which changes over the course of time (due to an aceleration, like gravity), so if you have any velocities which aren't changed instantaniously (anything more complex then "vel=c when player presses button, vel=0 when player bumps wall) then you'll probably want to use variables to keep track of your aceleration in the x and y directions or you're characters movement may vary depending on framerate.

if everything i just said is total greek to you and you're thinking "what the hell is this guy trying to tell me to do???" then just ask and i'll explain it in more detail for ya :) or maybe there's an easier method that someone else will post...

robotz
January 16th, 2008, 08:34 PM
Yes that made sense, thank you :) I'm very new to AS3 and am probably bringing over "old habits" from previous languages, but of course each language has its own specific quirks.

Just out of interest what do you use to handle your "main game loop"?

A lot of the examples I've seen use an event listener based on enter_frame that calls a function which, to all intents and purposes, is the "main loop" of the game.

The problem with this is that I'm at the mercy of the Flash frame rate setting again. How do you get a loop to, well.. loop as fast as it can, and not at the speed of the frame rate? i.e. not on an enter_frame event - while at the same time not causing flash or the browser to die by maxing out the CPU! :)

oldmanwinter
January 16th, 2008, 08:47 PM
Yes that made sense, thank you :) I'm very new to AS3 and am probably bringing over "old habits" from previous languages, but of course each language has its own specific quirks.

Just out of interest what do you use to handle your "main game loop"?

A lot of the examples I've seen use an event listener based on enter_frame that calls a function which, to all intents and purposes, is the "main loop" of the game.

The problem with this is that I'm at the mercy of the Flash frame rate setting again. How do you get a loop to, well.. loop as fast as it can, and not at the speed of the frame rate? i.e. not on an enter_frame event - while at the same time not causing flash or the browser to die by maxing out the CPU! :)

oh wow, i haven't even thought of that, i've just been using onEnterFrame=function(){game_code()}, and i've set the frame rate to 60 fps (the human eye can't really tell past something like 30 or 40, right?). i suppose you could put the game code in an endless loop which executes at the frame's load event, but i've never tried it so i can't say if it would work or not

EDIT: btw, i don't know if the above code would work for AS3, i've been using AS2

robotz
January 16th, 2008, 08:55 PM
I just tried a quick test to see what happens and it basically hangs! trace() events don't get fired for example and nothing updates. In my test script I ran the loop for 10 seconds, and after 10 seconds was up all the output was displayed / dumped in one go.

Unless there is a means to force flash to 'draw' everything I'm a bit stuck.

If you set the frame rate to 60 fps, and it's running on a crappy old PC that only manages 10 fps, the enter frame event only fires 10 times per second I believe. Does anyone know if there is a way around this? (or is the enter frame event simply as fast as Flash can possibly go?)

-Z-
January 16th, 2008, 10:13 PM
I always use timer events, and set the timer to 10-30 miliseconds, but inside the function, I have a Delta Time system,a bit different, it just checks to see if the total change in time since the last time it ran is over (my specific target fps), if so, it runs the stuff in there, and updates the delta time to start counting over again.

Marz
January 16th, 2008, 10:18 PM
Unfortunately, you can't do what you use to be able to do in old DOS TurboCLite days and create an endless while loop that would desist when quit was equal to a number.

If I remember correctly, Flash does not like endless loops... Even though it'll technically end.. sometime... ? :)

But the way I use to do them in those times were create a while loop that would continue to loop around until you hit a certain character or whatever.

tarwin
January 16th, 2008, 11:25 PM
I've used timers for games I've created in the past. Just know that timers don't go on exactly the ms you want them to, so don't trust them exactly (especially for music based games).

If you're animation really matters it can still be useful to use ENTER_FRAME events.

You'd be horrified how much difference there is between browsers / computers / setups in terms of speed though. And Flash is not very greedy either, and sometimes just sits on 18FPS but running 1/2 the speed you've told it to. The strange thing is that when you push the framerate to for example 50FPS it's more likely to try and grab more CPU than if you put it at 30FPS.

hatu
January 17th, 2008, 03:58 AM
I just tried a quick test to see what happens and it basically hangs! trace() events don't get fired for example and nothing updates. In my test script I ran the loop for 10 seconds, and after 10 seconds was up all the output was displayed / dumped in one go.

Unless there is a means to force flash to 'draw' everything I'm a bit stuck.

If you set the frame rate to 60 fps, and it's running on a crappy old PC that only manages 10 fps, the enter frame event only fires 10 times per second I believe. Does anyone know if there is a way around this? (or is the enter frame event simply as fast as Flash can possibly go?)

Just don't use EnterFrame for anything but rendering.
Put your movement code and the like on Timers and everything will work the same on 1fps and 100fps except less smoothly.

I don't think you should try to get everything update as fast as possible in the game loop. Almost nothing needs to fire 100 times a second.
For movement I use 40fps or 25ms/action(same thing) and it is very smooth.

If you're getting 10fps you either have terrible code or a terrible PC

robotz
January 17th, 2008, 06:09 AM
I played a lot more with this last night, and read an excellent article (http://www.kaourantin.net/2006/05/frame-rates-in-flash-player.html) by Tinic on why frame rates in Flash are so unpredictable.

-Z- : Yes I'm beginning to appreciate this now :) I'm now doing it similar to yours. I want to get a consistent 30 fps, so my internal game timer is ticking every 33ms/33ms/34ms (x10) and firing an event, so every 30 ticks I know 1 real second has passed. I've updated the code this morning to 'catch up', should say the render loop have taken longer than I expected (i.e. target PC is slow). I should get an end result very similar to yours.

As you said Marz, there is no "loop / force update" possibility here. As I read after posting my message browsers will force set frame rates and CPU use anyway, so I can see why this will never happen. I was amazed that IE allows for 100fps while Firefox halves that.

hatu - It's not about updating the game 100 times a second (I'm using a delta timer to base my game timings on), it was about trying to make the delta timer as accurate as possible! The faster my loop ran, the more accurate my timings would be. But I think I've read enough spread across various blogs and forums to appreciate Flash just doesn't work like that, so time to leave old-skool game coder habits behind and embrace the enter_frame.

Marz
January 17th, 2008, 01:31 PM
so time to leave old-skool game coder habits behind and embrace the enter_frame.

Ain't THAT the truth! *lol*

tarwin
January 17th, 2008, 07:20 PM
Using ticks of "33ms/33ms/34ms" won't actually get you exactly 30 ticks per second anyway, as Flash (even AS3) only does these ticks on the closest frame to your ms anyway. Putting the framerate to 120, then using 30tps timer, and animating all your frames by code could make this closer. The other problem is that Flash's timer incrementally goes out of time. So say you're first tick is at 35ms, your second will try and be 33ms after (min 33, but probably more) so might be at 70ms. This means by your 3rd tick it's probably already at 103ms -> 110ms depending on how your machine is running.

Flash runs really badly in Firefox 2. This extreme throttling problem has been fixed in FF3 beta and hopefully will be fine in the final. It is also throttled slightly by IE 6 / 7, not at all by Safari (PC at least) and in most cases not by Opera either (although I think if Opera things the Flash is advertisement sized it throttles the crap out of it - so Flash menus are a problem).

tarwin
January 17th, 2008, 07:21 PM
Oh here's something - sorry for multiple reply.

It can be good to rely on ENTER_FRAME events for specific things such as parallaxing backgrounds as you want these to move (not not move) every update frame.

robotz
January 17th, 2008, 09:13 PM
Hi Tarwin - thanks for the input. Since posting I have been playing more and more with this, and am finally happy I've got a solution that works. I was initially happy at setting the frame rate to 120 and counting the ticks + updating myself, but this was so inconsistent (even with timer checks to make the ticks catch-up) that I simplified it and use a simple timer check now, with the movement increments calculated off the time differences. At 10 fps it's choppy but works, at 30 fps it's perfect.

Do you have any idea how many events you can start firing off before it begins to drag Flash down? Also am I right in thinking you can only attach an enter frame event to a movieclip? (I was trying to avoid using MCs if I could).

tarwin
January 17th, 2008, 09:21 PM
Yeah I'm not sure if Sprite can have an ENTER_FRAME event. Or is sent one automatically I should say.

You could use Sprite as long as it extends EvenDispatcher (I think it does - docs will tell you) and then just add your own even listener to it.

neodeltai
February 4th, 2008, 02:24 PM
Yeah I'm not sure if Sprite can have an ENTER_FRAME event. Or is sent one automatically I should say.

What I've been doing is this:

- Set the frameRate to 1000.

- A Clock class listens for the stage's ENTER_FRAME event. In the listener, calculate the time since the last frame. Store that time in a public variable, like seconds:Number.

- The game's Engine listens for the stage's ENTER_FRAME event (make sure the Clock listens first!). In the listener, call an update(seconds:Number) function for anything that has time-based calculations to do (like animation, physics, etc.)

It's more-or-less worked for me, but I'm almost positive it's not the most efficient. If anyone else has a better system, I'd love to hear it. What do most flash games use to achieve stable animation?

Sirisian
February 4th, 2008, 09:12 PM
Google is fun :) (http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/utils/package.html#getTimer())