FPS, frame MS and frame stepping helper
BlitzMax Forums/BlitzMax Programming/FPS, frame MS and frame stepping helper
| ||
NOTICE: This will NOT help with the speed or smoothness of your game. It will however tell you how smooth it goes. Here's my little FPS and frame MS helper I use in random projects. It's a quick way to get an FPS counter into your project and also find out how long it takes to render each frame. It also comes with a cheap way of doing frame stepping. (pausing time and moving one frame ahead) And also a sort of history graph for both FPS and frame MS. So instead of using something like Fraps or Dxtory, you can just import this. You'll find it over at https://bitbucket.org/Hezkore/tfps Along with an example. Feel free to use it or improve it. If you do improve it somehow, please share it. :) ![]() |
| ||
Hi Hezkore: * Errm ... BlitzMAX has a unique way of handling how fast something goes. They use a command called CreateTimer() I wrote code to demonstrate this earlier HERE: Updated: 04/07/16 http://www.blitzbasic.com/Community/post.php?topic=105731&post=1293684 |
| ||
This has nothing to do with handling time or handling how fast things go. It's about telling you how efficient your game is running. I can for example tell you that your rain example runs at roughly 59 frames per second, and that it takes 17-18 milliseconds to render each frame. I can also pause time and slowly move through each frame and actually see the rain drops being created on the screen thanks to the frame stepping. Btw, you shouldn't rely on CreateTimer() and your link is broken. |
| ||
18ms ...is what it should take as dw is using "Delay 18" in the code. bye Ron |
| ||
16ms is what he's using, which would result in about a 62,5 FPS. But since delay is not very exact and only does a "minimum"of 16ms delay, he ends up with a slightly higher delay and lands at about 59 FPS. Which is why the delay function isn't always the best thing to use. ![]() |
| ||
Ok, then delaying 16 - rest is the drawing/flipping. So the reason for having a lower amount of fps is the speed of your machine. If "draw + flip" happens in <1ms, the delay is nearly the only "time taking" command. The slower your computer/gpu, the less accurate "Delay 16" will behave to the expectation. I am using a custom delta timer which tries to delay some time too (cpu load ) but only if frame rate capping is active. -> instead of delaying a big pile of milliseconds at once, I only delay for 1 millisecond and skip doing things if there isn't enough time gone. So instead of "loop update delay16" I have an "loop update delay1? | loop skipUpdate delay1? | loop skipUpdate delay1? | ..."-approach. bye Ron |
| ||
Yeah most of the rest is the drawing. But even with no flipping or drawing, delay won't be exact as it only does a minimum of the time you've specified. It kinda depends on your background processes, those are given some time to work while a delay is active. So it's not until those background processes say it's okay to continue that the delay ends. (kinda) It usually isn't a much longer delay, but it's not very exact and should probably not be used for important timing stuff (like FPS) in a proper project. |
| ||
I still do not get what your code exactly does: - there is an "Update()" which I am supposed to call ... to call when? - - call it during the RenderWorld-call? No ... as it handles Keyboard-actions - - call it during the UpdateWorld-call? No ... as it measures render times... Think it should be split into things done at a logical-update (updateWorld) and things done during rendering. For now this is not true: It's a quick way to get an FPS counter into your projects and also find out how long it takes to render each frames. It measures how long the whole "update+render"-thingie takes. If you now use that Update in your "RenderWorld"-function only, you are making it inaccurate as it uses KeyHit/FlushKeys (something "logical") within a function only doing "draw this here and there". If you extract that Key-handling into a custom function ("HandleInput()") you could call it in your update-function and this way keep the normal "Update()" function clean. This eg. allows for a 200hz update rate (and its input handling) compared to a low 30Hz render rate. Do not get me wrong: it works, but imho all of our projects and sourcecodes provide some bits to optimize here and there :-) bye Ron |
| ||
The only time it actually uses key inputs is when it's taking control of the application. (via frame stepping) Which I'll admit isn't the best at its current stage heh. But since the game is paused anyways, it doesn't really matter as you're the once advancing frames and not the game anymore. Throw TFPS.Update() in right before your flip and just call Print TFPS.FPS() anywhere and you're done. Or use Print TFPS.FrameMS() if you wan't some more exact data on how long it takes to render your frames. It's really just a simple counter for how many frames you've got per second. But it's good for spotting slowdowns in your game. Handling the speed of your game is something different. |
| ||
Here's en example showing it all. If you drag the window around, you'll see the lag spikes quite clearly. You don't have to use any of the frame stepping stuff or history graphs. You could (as I mentioned above) just call TFPS.Update() before you flip the buffers, then at any point call TFPS.FPS() to see how smooth the game is going. <Code removed, see first post> |
| ||
Sorry 'bout that. Fixed the link. And yes, DELAY is quick and dirty. Methods involving FPS counters and CreateTimer() are preferable for high accuracy in timing animation effects. |
| ||
Ok, found something to optimize ;-) you are iterating over the array and moving one after another to the previous spot (x[i] = x[i+1]). The optimization is to use a currentPosition / arrayCursor ... this cursor is increased/decreased and wraps at 0 or max (aka "x = (x + 1) mod array.length"). While the 10-sized array might not benefit from it ("mod" is rather expensive) that much, the 128-sized array will do. Sorry for "nitpicking" but I wouldn't let you go with something useful ;-) bye Ron |
| ||
Yeah thanks Derron! I actually had it like that at first. :) But I didn't really notice much of an impact on speed and I didn't like when it looped back to the start (was a bit confusing to watch) so I chose this method instead. If we could somehow still make the right side of the history graph always be the newest frame I'd do your method. The code is now hosted over at Bitbucket. It'll make sure that the code is always up to date and not lost here on the forums. I've also updated it so that you no longer have to call TFPS.Update() Oh and it's now a module heh. Import the module and just call TFPS.FPS() to see your current FPS. |
| ||
@right side of the historygraph Just use the "currentPosition" (or how you call) it counter to find out the starting index. Instead of for local bla:int = EachIn array you then do local arrayIndex:int = currentPosition for local offset:int = 0 until array.length arrayIndex = (currentPosition + offset) mod array.length ... The "newest" is always before (or after) the "currentPosition" value... bye Ron |
| ||
Ah yes, thank you. I'll try to get that in some time! :) |
| ||
Nice demo! I find FPS-related stuff gets really complicated once you get into it, so much so that I can't really deal with it, but that demo visualises the frame spikes really well, even from clicking on other windows and the like... looks very smooth to me, too. |