View Full Version : Yet another timing thread
Mike Boeh
05-19-2006, 07:38 AM
As I see it, there are 4 ways people do timing. Can someone tell my why my opinions are wrong here?
1. Simple fixed rate timer
Basically, the game waits for x ms to expire before processing the game loop.
Pros: The easiest to implement
Cons: Unless your internal timer is the same as the refresh rate, it will not be silk smooth.
Example: Platypus, Demonstar
My Opinion :) This is very basic, but it works. Lots of new coders use it.
2. High frequency internal timer, render at refresh rate
This is where the game runs internally at, say, 250 fps and will run its game logic the needed amount of times to keep up with the refresh rate.
Pros: Fairly easy to implement, very precise collisions, silk smooth in most cases.
Cons: Some refresh rates are not 100% smooth, depending on internal frequency. If internal logic rate exceeds the internal fps, the result will be a nasty slowdown. Not efficient.
Examples: Bricks of Atlantis, Bugatron, Pocket Tanks
My Opinion :) This works surprisingly well. I used it for Cosmo Bots and it always appears smooth. However, in my games, my internal logic is always so simple that it can never get to the "Nintendo Slowdown" point. And I cap it to avoid this. Still, in low fps-situations, you are burning a lot of cycles for the game's logic that aren't really necessary.
3. Delta Value Timing
This is where the game runs as fast as it can, and the "amount of time passed" is sent to the logic loops and objects move at their speed*time_passed.
Pros: Always silk smooth, works even in very low fps situations, easy to implement, efficient.
Cons: Can be tricky with physics/collisions, can make code messy
Example: Heavy Weapon, Lego Builder Bots
My Opinion :) Although it's easy to get in there, it means that time is factor in all movement- basically adding another variable to deal with. This causes the code to be more messy in the long run. Also, it's really tricky to get stuff like acceleration to work exactly the same on all computers. If you can deal with all that, it is smooth though.
4. Low internal fps with tweening
This is where the game runs very slowly internally, say 25 fps. And smooths the rendering between the last two frames based on a time variable.
Pros: Efficient, silk smooth, easy physics.
Cons: Tricky to implement, inprecise collisions
Examples: Best Friends, Quake 2
My Opinion :) This is my favorite method. It's efficient and looks nice. The only problem I have is that getting it to work "just right" takes a lot of fiddling- especially when objects become visible for the first time.
I recently switched my current project from #2 to #4, and it wasn't fun, but it's working good now. In high fps situations (geforce card, etc) I see no actual difference though. On the low end, it does seem to run a bit better.
Fabio
05-19-2006, 08:10 AM
I synch to the video and then compute one (or more, to not alea/miss collisions) physics steps. Also, my mouse/keyboard input handlers' events are timestamped so if necessary I can take into account also that in my physics engine (to extend the usefullness of the multi-steps approach).
Ideally I run only one physics iteration/step per frame but, if it becomes necessary (expecially for collision) to avoid aliasing, I divide that frame into n necessary steps (n must be evaluated depending on speed, etc.. here some raycasting collision prediction method helps).
IMO the real problem is not much the timing method you use, but the fact that framerate is not constant. The method I use (described above) is in my experience better than the 4 you mentioned, but neither this will make the animation smooth as silk if the rendering takes "randomly" 1 frame now, 2 frames then, etc..
The PC is not really an ideal platform for achieving easily constant frame rate, expecially in 3D games (that's what I was thinking about, anyway). For 2D games it's much easier though (the #4 is a good comprimise IMHO, because it removes most of the aliasing). Never seen too much physics in 2D games anyway.
Mike Boeh
05-19-2006, 08:17 AM
IMO the real problem is not much the timing method you use, but the fact that framerate is not constant. The method I use (described above) is in my experience better than the 4 you mentioned, but neither this will make the animation smooth as silk if the rendering takes "randomly" 1 frame now, 2 frames then, etc..
#4 is perfectly smooth in that situation. That's what the "tween" is for at render-time....
Fabio
05-19-2006, 08:28 AM
By the way.. one idea I have that I should implement is to use the timestamp to force additional physics steps, so that all inputs are useful for the simulation.
Anyway, all of this is going to make a difference only on very low FPS, which is though undesiderable by itself, so I think that for 3D games #3 method + the "1 or more physics steps" (as described in my previous post) may be the best compromise.
The rules for me are: never compute more than can be seen && never waste inputs.
Physics algorithms tend to be unstable, as you said mentioning acceleration (but then there's also curved movements, etc..), thus at least inputs should not be discarded, and always acted upon.
I've been tempted several times to implement something similar to your #4 though, so I think (even++ more for 2D games) that you are making the right choice. When you're ready to draw a frame, compute an additional time (meaning when it will be actually displayed) and then interpolate/extrapolate objects positions to eliminate aliasing even if your fps are different than your fixed 25Hz objects "physics" update. It will look smooth, but will have some visual latency. Normally a player doesn't notice 10-30ms of latency between hands output and visual input anyway.
lakibuk
05-19-2006, 08:28 AM
I am using #2 in my current project. You have posted this method some time ago. Hope i've implemented it right. In my first game i used #3, didn't like it. Strange that i don't get smooth movements in any of these two, maybe i am doing it wrong?
Fabio
05-19-2006, 08:36 AM
#4 is perfectly smooth in that situation. That's what the "tween" is for at render-time....
yes, but:
1) it will add latency.
2) no method can save your smooth animation if the rendering takes more than you foresaw. Imagine the loop.. and suddenly, after you've computed the positions of the objects for the next frame, then rendering took one frame more than you were expecting. The player will unavoidably see with some ms (1 frame) of delay objects in a position not representative of the real time they appeared on screen.
In a simple 2D game it is quite easy to get constant framerate (or compute how long it will take to render it, and thus show the objects in the right position), but in a complex scene/fx 3D game that has to run on a lot of different configurations it will be hard.
Mike Boeh
05-19-2006, 08:43 AM
I think I know what you're saying...
Let's say I calculate a tween value of .655F and have 20 items to render.
If the first 10 items take more than 1 ms to render, then the next 10 will actually be "off" by that 1 ms.
Is that what you mean? And are you the same OpenGL programmer who wrote something for Ola? I can't imagine there are too many Fabios around :)
luggage
05-19-2006, 09:06 AM
We use #3 here. Everything pretty much has the following functions.
Initialise()
Update( FP delta )
Render()
Shutdown()
The Update function has the time delta passed through in seconds.
A good test is to pass through 0.0f as your delta to the update loop. Everything should remain stationary as if the game is paused. If something is still moving then it's not framerate independant and needs to be fixed.
Fabio
05-19-2006, 09:55 AM
Hi Mike,
I think I know what you're saying...
Let's say I calculate a tween value of .655F and have 20 items to render.
If the first 10 items take more than 1 ms to render, then the next 10 will actually be "off" by that 1 ms.
Is that what you mean? Well, english is not my native language so sometimes it's hard to express myself and also to understand the replies.
As I understand (please correct me if I'm wrong) tweening means interpolating inbetween two (or more, for e.g. cubic interpolation) frames (meant exclusively as computed objects coordinates, not gfx yet) which are generated at a fixed rate (let's say 25Hz).
So we have a freerunning, 25Hz generator of the world's objects coordinates, and another independent free running "renderer" that has to give a visual representation of what the world is and, to avoid time-aliasing, it must be able to do it for any moment, not just those fixed 25Hz steps, because the display is not necessarily in synch with this 25Hz game engine.
Here comes interpolation (with all its problems and limitations!).
Latency is unavoidably added because to have an accurate enough interpolation, cubic-interpolation should be the very minimum, meaning 3 or 4 frames must be available (thus we've to delay visual representation of 2 frames, otherwise we don't have enough data to interpolate yet).
This method is anyway very good, and by no suprise (although I admit I learnt it thanks to you now) John Carmack used it in Quake2 (maybe even 3? I suspect his choice had to do also with the need for an optimal solution for internet based multiplayer algorithms).
When I say that no method in the world can save you from a certain problem, I mean that whatever is the way you're computing the coordinates of the objects (necessarily) before rendering them on screen, that image will have to represent the world (with a constant delay if we want) as it would be the exact moment when the image hits the retina and reachs the brain.
If you lose control over this (e.g. Windows starts swapping; or doesn't give your process enough CPU that frame; or the scene to be rendered is too complex and takes extra frames to be rendered), then an additional, unpredictable delay will appear between your chosen "time appearing on the image" and the actual display. This will kill smoothness, we can't help it.
The possible solutions are:
1) constant framerate (all is predictable)
2) while we can't help if it's Windows that suddenly freezes or slows down our process, we can at least foresee how many frames it will take to render the frame we're going to render (basing e.g. on the number of objects that are going to be drawn for that frame, their size and fx) and thus if we e.g. evaluate that the next frame will take 1 more vertical refresh (of course I always assumed VBL synched to avoid tearing, which is very unprofessional IMHO) we should not draw the objects at the coordinates we were going to use, but at those delayed by the right amount, so when the image will hit the retina, it will show the objects where they would be at THAT time.
To make a (voluntarily exaggerated) example: our PC gfx card has a refresh rate of 100Hz and takes 10 ms (1 frame) to draw up to 10 objects, 20 ms to draw up to 20 objects, and so on.
We have almost always <= 10 objects per frame, but at a certain point we have 12. Assuming 100Hz framerate:
TrueTime N.Objs. SimTimeToRender TimeThatTheDisplayShows
000ms 8 000ms ---
010ms 7 010ms 000ms
020ms 9 020ms 010ms
030ms 12 030ms 020ms
stalled 020ms
050ms 8 050ms 030ms
060ms 9 060ms 050ms
at TrueTime 30ms we expected that the player would have got his new image 10ms after, so we sent him world coordinates 030ms, but the renderer stalled and the image actually appeared 10ms later, thus showing objects in a place wrong by 10ms. What causes jerking is not much the replication of the 020ms frame, it is instead the 030ms image appearing at TrueTime 050ms (should have appeared the 040ms image), and this is a first jerking, and then another one follows immediately after: an image step from 030ms to 050ms in just 10ms.
When we were going to draw 12 objects, if we knew that that would have taken one extra 10ms to be done, we would have cancelled it and sent the next 10ms world coordinates to the renderer:
TrueTime N.Objs. SimTimeToRender TimeThatTheDisplayShows
000ms 8 000ms ---
010ms 7 010ms 000ms
020ms 9 020ms 010ms
030ms 12! 040ms 020ms
I knew this was going to happen 020ms
050ms 8 050ms 040ms
060ms 9 060ms 050ms The player thus would have always seen images coherent with time.
The only remaining unpleasant effect is that one frame will not be rendered, but this is not going to cause real disturb, and there are really no solutions for this latter problem, besides upgrade the gfx board with a more capable one or reduce the complexity of those frames that would take more to render, thus making rendering time constant (and turning the previous system useless).
For this whole timing and smoothness problem, the ideal solution IMHO would to choose a fixed framerate (not necessarily during design, but maybe depending on the PC power we're running on) which has to be a n integer multiple of the refresh rate, keep our fps absolutely constant, run physics/game_logic with it (no time-aliasing, no latency due to #4 interpolation). Cons? Scene complexity must be reduced (number of displayed objects and/or quality of effects) when we evaluate that the renderer is not going to cope with it. Another con is that if the scene complexity is very low, we aren't going to be able to exploit it to get higher fps.
I think though that this method will be very viable when motion blur will be too, and thus we'll use a constant 25fps framerate (with an integer multiple refresh rate, say 100Hz for monitors, or 50Hz for PAL TV system) and eventually reduce image complexity when necessary.
We'll be able to run the physics/game_logic perfectly in synch with the display rendering, thus having it perfectly smooth, without delay/latency, and with best possible efficiency.
With motion blur we won't need more than 25fps anyway to get perfectly smooth images. Non motion blurred fps >=25 look better simply because the added frames someway compensate the lack of motion blur, getting merged by the natural persistence of the retina.
And are you the same OpenGL programmer who wrote something for Ola? I can't imagine there are too many Fabios around :) ssssssssssshh!! yes it's me. ;) he told me many many nice things about you, by the way, during the many years. :)
Mike Boeh
05-19-2006, 10:24 AM
Regarding the latency, yes that's the major side effect of tweening. I am using a 25 hz clock currently, which means that the logic loop is only run once per 40 ms... Here's a simplified version of my loop (the one I actually use accounts for alt-tabs and that kind of stuff)
#define INTERNAL_MS 40
//how much time has passed since we last were here
elapsed = timer.Check(1000) - lastLogicTime;
//ticks is the number of times we need to run our logic. Usually this will
//be 0 or 1, but in slow cases, it could be higher
int ticks=elapsed/INTERNAL_MS;
for(int k=0; k<ticks; ++k)
{
lastLogicTime=lastLogicTime+INTERNAL_MS;
doLogic();
}
//so tween is the amount of interpolation to do between the last
//position and current position
float tween= (float)(elapsed % INTERNAL_MS)/(float)INTERNAL_MS;
doRender(tween);
If you changed INTERNAL_MS to, say, 4... Then you wouldn't have to calculate a tween at all, and it basically becomes method #2....
So in this situation, latency could be as low as 0, or as high as 80 ms..... The only thing that would be really easy to notice with this would be the mouse cursor. So for it, I make an exception and update its position at render time. I think all the Id games still use this method, but I was only sure about Quake 2....
Hey maybe the tween could be calculated for each object individually. I wonder how much overhead a high-performance timer call has :)
For this whole timing and smoothness problem, the ideal solution IMHO would to choose a fixed framerate (not necessarily during design, but maybe depending on the PC power we're running on) which has to be a n integer multiple of the refresh rate, keep our fps absolutely constant, run physics/game_logic with it (no time-aliasing, no latency due to #4 interpolation). Cons? Scene complexity must be reduced (number of displayed objects and/or quality of effects) when we evaluate that the renderer is not going to cope with it. Another con is that if the scene complexity is very low, we aren't going to be able to exploit it to get higher fps.
Yup that would be ideal, but varying the internal update rate changes how acceleration affects objects and collision precision...
Ola said good things about you too- something about writing a really nice/fast OpenGL layer. BTW for anyone wondering, Ola is the founder of Arcadelab- Daniel's brother.
svero
05-19-2006, 10:32 AM
I've been using #2 at 125 f/s internally in the logic loops. Sometimes, to optimise, I'll trim back certain things by only doing them every "x" logic frames. I've never run into many optimizing issues using this method though. It runs pretty good even on slower machines for quite complex games logic wise. It's not always perfectly smooth dependingon the frame rate, but it's generally "good enough" for my purposes. + I really like having a dependable constant frame rate to use as a pseudo timer. I find it keeps the code quite simple and nice.
Emmanuel
05-19-2006, 10:37 AM
I've used #3 for Fairies; while it's silky smooth, it does make the code very messy, so for Mystic Inn and the new title we've started working on, I've switched to #2, updating logic at 100 fps, except for some logic reconciliation steps that don't contain any movement and only need to be done once per rendered frame.
Best regards,
Emmanuel
Fabio
05-19-2006, 10:43 AM
Hey maybe the tween could be calculated for each object individually. At each (25Hz) clock you may compute each objects coordinates and store them. Keep the last 4 buffers for cubic interpolation, or 2 for linear. Then interpolate (assume a fixed delay, which will be of course greater in case of cubic interpolation, then add the foreseen/evaluated time the renderer will take) the objects coordinates to show with good approximation where they are at any fractional time due for display.
I wonder how much overhead a high-performance timer call has :)Multimedia timers don't have much overhead anyway neither on NT based OS's and with 1ms resolution. A modern machine can cope perfectly even with 1ms timers, although it's not ideal.
Yup that would be ideal, but varying the internal update rate changes how acceleration affects objects and collision precision... I've always assumed constant internal update rate here.
About Ola.. we've been very good friends since about 12 years ago.. met IRL, always stayed in touch. I've the greatest respect and esteem for him as a person, but I also think that he's not only a great pixel artist (as many know) but also a very talented and experienced coder, although nowadays he enjoys mostly to express himself through his pixel art and game design (well, when you finish developing your dream game engine, and all the tools (ArtGem for example) you don't have much more left to code ;) ).
Mike Boeh
05-19-2006, 11:05 AM
@Fabio: I never considered using cubit interpolation, I think it's beyond the scope of my 2d project :)
@Emmanuel/Svero: 125hz and 100hz? What happens if the monitor is at 85hz? Some frames logic would run once, others twice. I would think that would be choppy....
PeterM
05-19-2006, 12:17 PM
Some frames would have several updates performed, but it ends up not mattering - the tweening should still be fine depending on how you calculate things for your loop. I use the method at Gaffer's articles without any troubles.
http://www.gaffer.org/articles/Timestep.html
Note that Ysaneya at GameDev.net has been having trouble with this method - but as far as I can tell it stems from him not being able to guarantee that his physics on average takes less time than his allocated timestep, which is a requirement for fixing your logic timestep.
http://www.gamedev.net/community/forums/topic.asp?topic_id=393475
TheMysteriousStranger
05-19-2006, 12:53 PM
Personally I prefer #3. Although it can get messy and some of the maths can be a real mind-bender to figure out sometimes, it has one major advantage - reliability. It doesn't matter if the target computer runs 10x faster than your dev machine or 10x slower, a good delta time algorithm will always produce the same results, just at a different fps. I personally limit my delta time to no faster than 400fps, as a kind of future proofing (for when computers can play the game so fast that the variables can no longer detect the time between frames). I also find delta time is very good for precision in collisions - e.g. when you want to move an object backwards by it's collision depth with another object, you can do so extremely precisely.
Plus, once you get used to thinking in terms of time rather than distance, the maths involved becomes simpler and the messy code becomes more readable. At least, to yourself :)
Also, when it comes to physics and delta time, you can still use fixed-rate steps, you simply find out how many steps are needed when the object moves delta*velocity in that frame.
But as has been said already - it all depends on the game. For some games, the other timing methods are every bit as good or better then delta time, and require less work to implement. I mostly use delta time because it was the way I was taught to do timing and it's integrated into my framework so much that it will take me ages to switch to another method.
Rainer Deyke
05-19-2006, 01:18 PM
Actually #3 is by far the least reliable method, and should not be used, ever. Consider the following:
1. You are running on a very slow computer, or experience a sudden slow-down on a fast computer. As your movement delta is multiplied by a large time value, your system loses numerical stability. Depending on your collision detection system, objects may even move through other objects.
2. You are running on a very fast computer. As delta time tends toward zero, movement vectors lose accuracy, and objects may stop moving at all.
3. Even under normal circumstances, moving 10 times by 1/10 unit will yield different results than moving 11 times by 1/11 unit.
4. An object, moving at some (constant or variable) speed, fires missiles at a constant rate. To correctly handle this case, you would need to: Keep track of the timer value from frame to frame. Calculate how many missiles (0 or more) are fired in the current update. Calculate where the object was when it fired each of those missiles, and fire the missiles from that location. Adjust the position of the missiles so that the missiles fired earlier in the frame have already moved forward by the end of the frame.
Chances are you'll get the calculations wrong somewhere along the line, and it'll still look close enough to correct most of the time that you don't notice that there's an error.
princec
05-19-2006, 01:20 PM
Being an idiot I stick with #1 (and preferably with Vsync on). My game logic is utterly trivial and uses almost no CPU, and I simply design the games to run at 60fps on the minimum spec. So easy it hurts. And always silky smooth.
Cas :)
Mike Boeh
05-19-2006, 01:32 PM
Being an idiot I stick with #1 (and preferably with Vsync on). My game logic is utterly trivial and uses almost no CPU, and I simply design the games to run at 60fps on the minimum spec. So easy it hurts. And always silky smooth.
What if the screen refresh rate is 100 hz, and vsync is on? In that case it will not be silky smooth.
TheMysteriousStranger
05-19-2006, 01:47 PM
Rainer Deyke - all of those problems you listed there are fixed by one simple solution - set a minimum and maximum delta value per frame. And point 4 is where the code gets messy and the maths complicated. Yes, there is a chance that you'll make small errors in the code, but as long as those errors provide results that look and act like the user expects, then they are not serious issues. It's only when you deal with physics reactions that the precision becomes a concern, and then it's matter of making sure the physics steps are working with the delta time, not against it.
The other methods listed can be problematic because they can lose sync with the screen, just like Fabio has been pointing out. With delta time, the calculations are not always 100% perfect, but they are in sync with what the user experiences (assuming a correct implementation - there's a lot of room for developer error in delta time programming). Sometimes, especially in visually rich games, appearances are more important than precision.
Jesse Aldridge
05-19-2006, 01:52 PM
1. Simple fixed rate timer
Basically, the game waits for x ms to expire before processing the game loop.
Pros: The easiest to implement
Cons: Unless your internal timer is the same as the refresh rate, it will not be silk smooth.
Doesn't vsync mean the game will get rendered at the refresh rate?
Does this mean that with vsync on #1 has no disadvantages?
Edit: oh wait, i get it
Mike Boeh
05-19-2006, 02:37 PM
I am beginning to think I wasted two days doing #4, and might go back to #2... Getting 2 things to bounce off each other properly at 25hz is a real pain! :(
Rainer Deyke
05-19-2006, 03:23 PM
Where I come from, incorrect behavior is unacceptable, and slight variantions in behavior are always incorrect. How can you be sure that you won't get serious problems as the game simulatiuon slowly desynchronises?
For the record, I don't see any disadvantages to #4 at all, so long as the game simulation is reasonably fast and the internal frame rate isn't too low. I use an internal frame rate of 50 fps, which nicely sidesteps the artifacts caused by 25 fps updates.
PeterM
05-19-2006, 03:26 PM
(Edit) In reply to Mike:
Weird, how is it different to doing it using regular time-based movement?
I am beginning to think I wasted two days doing #4, and might go back to #2... Getting 2 things to bounce off each other properly at 25hz is a real pain! :(
Thats always a pain no matter which timing strategy you pick. Well, that is... if you want to do it as accurate as possible. See if there is a collision in this timeslice. If so, move the simulation to that time. Handle the collision. Then move on from there until you ran out of normalized time (dont forget to scale the normalized time fraction accordingly before subtracting it).
The higher the speed of the moving objects the lower the framerate will be. Its like that because you'll have more collisions per frame then (and each collision means sweeping everything against anything again).
Well, its pretty complicated and sorta weird. But it looks and feels awesome. In a breakout game for example you dont lose displacement as a collision side effect, which makes it a tad faster (especially that tunneling mass bounce stuff) and more realistic. It really feels damn solid.
But usually it isnt worth the trouble, methinks.
princec
05-19-2006, 05:36 PM
What if the screen refresh rate is 100 hz, and vsync is on? In that case it will not be silky smooth.
I attempt to change the display mode in fullscreen to 60Hz. If that fails, or it's windowed mode, I don't use vsync. Either way with vsync on or off I still use a timer to cap the framerate - there is no actual reliable way of knowing if vsync is indeed on.
Cas :)
Anthony Flack
05-19-2006, 07:49 PM
I've been using #2, running at about 300hz. The logic doesn't really have much overhead compared to the rendering, and it means that it copes with different refresh rates better.
However, I've never been able to get it properly smooth. Part of the problem is, I think, that using Blitz I only have access to a ms timer, and that doesn't seem quite good enough. I'm torn between locking the framerate (which improves things on fast computers) and leaving it floating (for computers that need to frameskip). Maybe I should do both, and have it intelligently select the appropriate one...
I've tried using an averaged framerate too, but that has weirdy side effects. Every time I fiddle with this I end up giving up after a while, with the intention of coming back to it later.
I hate timing code. I wish I had a fixed hardware platform to lock down the framerate to.
svero
05-19-2006, 08:19 PM
@Emmanuel/Svero: 125hz and 100hz? What happens if the monitor is at 85hz? Some frames logic would run once, others twice. I would think that would be choppy....
I've found there's a little chop, but that it's generally pretty smooth and not that noticeable unless you're really trying to look for it. I don't think it makes a difference for most if any players. I'd agree it's not perfect on the chop side, but I really like what it does internally code wise. Very clean and easy to work with.
Some frames would have several updates performed, but it ends up not mattering - the tweening should still be fine depending on how you calculate things for your loop. I use the method at Gaffer's articles without any troubles.
http://www.gaffer.org/articles/Timestep.html
This is basically Fabio's suggestion from above (#3 + 1 or more simulation updates), correct? Not challenging you here, just making sure I understand correctly.
Another thing about latency to consider is that if you are rendering to a OpenGL/D3D device, there are inherent latencies in the video driver as it buffers frames. If you are buffering 4 simulation frames before posting a rendering update, it could be up to another 3 rendering frames before the results are seen onscreen.
Something to consider if your renderer isn't clearly outpacing your simulation.
Chris Evans
05-19-2006, 10:59 PM
Rainer Deyke - all of those problems you listed there are fixed by one simple solution - set a minimum and maximum delta value per frame. And point 4 is where the code gets messy and the maths complicated. Yes, there is a chance that you'll make small errors in the code, but as long as those errors provide results that look and act like the user expects, then they are not serious issues. It's only when you deal with physics reactions that the precision becomes a concern, and then it's matter of making sure the physics steps are working with the delta time, not against it.
Yep. I've started using #3 with my last two games (one still in development). My golf 3D game uses #3 and my physics and collision have worked just fine. And anytime I've had oddities with collision it was due to other reasons, not the timing.
Sure it was a bit tricky setting up with my physics code, but I'm very happy with the results. My game runs silky smooth on fast computers and remains very playable on slower computers. For example, if a player on a fast computer putts the ball with the same power as a player on a slow computer, the ball will go the exact same distance and take the exact same time to come to a rest. The only difference is that on a fast computer the ball will move much smoother.
I'm using Shockwave (which has a fairly old 3D engine) and mostly do 3D games that are playable on the web, so using fixed frames is a kiss of death. I used a fixed timer with my first game and I got tons of reports of the game running sluggish even on mid-range systems. If the game couldn't keep up with the target frame rate, the game would basically run in slow motion and be unplayable (or unfun). Nowadays since I've switched to using a delta timer, the actual game speed is the same on fast and slow computers. I also put maximum value limits on object movements to prevent huge skips if the computer stutters for a brief moment. Collision has never been a problem because I do distance checks BEFORE I actually move the object. If a wall is 9 units away, I tabulate the move increment of the object and if the increment >= 9 units I know collision will occur with the current update so I don't add the increment. Instead, I may place the object right next to the wall. However, if the increment is < 9 units I can add the increment to the object. It doesn't matter if the increment is 5 or 2,343 units, the collision will be detected properly.
If you're doing games with simple logic code and low/no 3D requirements, you can pretty much try any of the options Mike B. brought up and be okay. But I think if you're doing a fairly demanding 3D game and want to run at a fairly consistent game speed on various system specs, then I highly recommend #3 and would avoid #1. I can't really comment on the other timing methods since I don't have much experience with them.
Fabio
05-19-2006, 11:57 PM
Another thing about latency to consider is that if you are rendering to a OpenGL/D3D device, there are inherent latencies in the video driver as it buffers frames. If you are buffering 4 simulation frames before posting a rendering update, it could be up to another 3 rendering frames before the results are seen onscreen. Indeed, and that not only increases latency, but worsens also the jerkness when that "unexpected" renderer-delay I described in my example happens.
I don't like to lose control of # of buffers, that's why in my OGL code (dunno if D3D is the same, never made my hands dirty with it ;) ), before entering the main loop, I issue many (say ten, in any case more than the maximum number of hidden buffers you can expect that there can be) glSwapBuffers() in sequence (clearing the screen with black), so the buffers queue will be empty when I finally enter the main rendering loop.
In more than one case this indeed *made* difference to get perfect smoothness.
Another thing you've to be sensitive about is Windows multitasking issues. After lotsa experimenting with priority classes and so on, I found that the best result (if you still want to have input and audio working on all PCs) is to set +1 priority in your rendering thread, normal priority class (yes, live with it) and multimedia timers resolution to 1ms. This will make the Windows multitasking scheduler work on a 1ms resolution too, turning interference from other processes less critical, although you still have a normal priority class for your process. Do not expect all things to work on all PCs if you set a higher priority for your process or anything above +1 for the thread.. this is a comment coming from me who would like to use REALTIME_PRIORITY_CLASS for his games if it was possible. ;)
dxgame
05-20-2006, 12:45 AM
3. Delta Value Timing My preferred choice. :)
"Actually #3 is by far the least reliable method, and should not be used, ever."
With all due respect, this just isn't true. ;)
"1. You are running on a very slow computer, or experience a sudden slow-down on a fast computer. As your movement delta is multiplied by a large time value, your system loses numerical stability. Depending on your collision detection system, objects may even move through other objects."
I've seen this same answer posted over and over. :confused: Just cap the delta so it never goes past a pre-determined value. Problem 100% solved.
"2. You are running on a very fast computer. As delta time tends toward zero, movement vectors lose accuracy, and objects may stop moving at all."
Again, simply make sure to cap your delta values so they never go past a min/max setting, and then you GAIN all the benefits of time based coding. Which is to allow newer computers to render at high frame rates, and slower computers to render at more coarse frame rates. No need for tweaning, processing the logic in one thread, rendering in another, etc, etc. :D
I also take it one step further by averaging the delta over the last 10 or so rendered frames, helps smooth out the movement even more.
Sharpfish
05-20-2006, 02:25 AM
#3 here and always has been, but then I do mostly 3D stuff and wouldn't want to try the others or combinations just yet (until I was using more advanced physics stuff also when it may become a problem).
#3 isn't perfect, but as DXgame says you cap the min/max and average it (someone on here told me about averaging last year and it works nice!) and it seems to work ok. Sometimes you get the odd mini-jerk or tiny stutter but that's windows + 3D I guess ;)
I also echo Anthony's statement "I hate timing code. I wish I had a fixed hardware platform to lock down the framerate to." Life would be so much simpler without timing issues and things like QPC problems on HT cpu (laptops etc).
princec
05-20-2006, 02:59 AM
I hate timing code. I wish I had a fixed hardware platform to lock down the framerate to.
So make your own! ChangeDisplaySettings to 60Hz, run both logic and render at 60Hz. No more hair pulling, no complex code, and crucially, no difference to the users. I just can't help but wonder programmers make work for themselves. If the users don't see any difference why do it any other way?
Cas :)
Sharpfish
05-20-2006, 03:07 AM
So make your own! ChangeDisplaySettings to 60Hz, run both logic and render at 60Hz. No more hair pulling, no complex code, and crucially, no difference to the users. I just can't help but wonder programmers make work for themselves. If the users don't see any difference why do it any other way?
Cas :)
I'm not getting at you (as If I would dare ;) ) but I would *never* alter the refresh rate or rely on fixed refresh. Sure it works (for you) but it's just something I wouldn't feel right doing. And if your game can't keep up with 60 then you get slowdown anyway so delta timing would still be needed.
That and the fact I never play a game @ 60hz for any length of time because I notice the flicker - I want at least 85hz refresh when I play. :)
princec
05-20-2006, 03:13 AM
I'm not getting at you (as If I would dare ;) ) but I would *never* alter the refresh rate or rely on fixed refresh. Sure it works (for you) but it's just something I wouldn't feel right doing. And if your game can't keep up with 60 then you get slowdown anyway so delta timing would still be needed.
That and the fact I never play a game @ 60hz for any length of time because I notice the flicker - I want at least 85hz refresh when I play. :)
You don't like consoles then? (And if my games can't keep up at 60Hz, they need adjusting until they can!)
Cas :)
Sharpfish
05-20-2006, 03:16 AM
You don't like consoles then? (And if my games can't keep up at 60Hz, they need adjusting until they can!)
Cas :)
(edit) > if my TV had visible flicker like my monitor does @ 60hz then I wouldn't like playing consoles. (a more succinct way of saying it)
I just got used to having higher/more comfy refresh rates on 3D (so it prob doesn't apply to your 2D stuff as much if at all I suppose). LCDs with slow response times are one thing (at their "60hz") but on a large CRT that can go uptp 100hz or more it seems like a backwards step to force the user to run in the lowest common denominator. I don't like punishing players.
Along those lines it's the same with capping frames at 30fps or something. Those who have decent systems and can get higher framerates and run in whatever refresh rate they want to should be able to. Though I realise of course everyone thinks different and it's just my take on it. :)
princec
05-20-2006, 04:09 AM
From the perspective of selling games, it makes not one iota of difference, it would seem. So why punish yourself grokking all those crazy newfangled techniques when the old fashioned way still works and still sells exactly the same as any other technique? :)
Cas :)
PeterM
05-20-2006, 04:14 AM
For PC, locking to 60Hz would be okay I guess. Presuming that it can be done reliably, which I guess it can if you've not had any trouble.
I wouldn't like to port the game to a PAL system though, so anyone hoping to get their game on Xbox Live Arcade should be careful.
princec
05-20-2006, 04:20 AM
In ye olden days running on PAL just meant the game was 20% slower ;) We never noticed over here...
You can't reliably get vsync (and you generally can't get it at all, in windowed mode) so you're really always relying on a hires timer frame rate cap in addition. I use the winmm multimedia timer accurate to 1ms for this purpose (as it is unaffected by Speedstep and multicores) and it's accurate enough.
Cas :)
>20%
16.67% (ntsc games are 20% faster than pal games) ;)
>You can't reliably get vsync (and you generally can't get it at all, in windowed mode)[...]
Vsync works in windowed mode with opengl on nvidia and ati cards. But I've often seen a fixed tear line in the upper third of the screen with ati setups. Dunno really whats the reason for that.
Guess you mixed that a bit up with java2d. Well, but its of course true that you cannot tell if enabling (trying to enable) vsync worked. With nvidia cards the current state can be querried, but thats the only exception. Other vendors dont think its necessary to follow the spec in that regard.
Ah well... backing it up with a framecap doesnt hurt anyways and its certainly more robust.
edit: Oh and even if you dont port it over to consoles, you still might get some PAL drag. I'm using an ati card right now and if tv-out and vsync are enabled I cannot exceed 50fps (hz of the primary display doesnt make a difference). Pretty annoying, isnt it?
princec
05-20-2006, 07:04 AM
>20%
16.67% (ntsc games are 20% faster than pal games) ;)
>You can't reliably get vsync (and you generally can't get it at all, in windowed mode)[...]
Vsync works in windowed mode with opengl on nvidia and ati cards. But I've often seen a fixed tear line in the upper third of the screen with ati setups. Dunno really whats the reason for that.
Guess you mixed that a bit up with java2d. Well, but its of course true that you cannot tell if enabling (trying to enable) vsync worked. With nvidia cards the current state can be querried, but thats the only exception. Other vendors dont think its necessary to follow the spec in that regard.
Ah well... backing it up with a framecap doesnt hurt anyways and its certainly more robust.
Pedant ;) Actually I've never used Java2D for anything other than GUIs so I don't have a clue how it works. But even nvidia cards lie about whether vsync is enabled or not because the user can force it off in the control panel. A lot of hardcore 3d FPSers do that for some unknown reason, but the end result is a game that runs at 1000fps instead of 60 which renders it unplayable.
Cas :)
luggage
05-20-2006, 07:07 AM
Actually #3 is by far the least reliable method, and should not be used, ever.Better let the folks at Epic know they're doing it all wrong with Unreal Engine 3 then. And pretty much every other retail game I know of.
I'm pretty sure Dead or Alive uses Cas' method though. Seeing as you can't play the game over here unless you have a tv that will do 60hz.
princec
05-20-2006, 07:16 AM
Better let the folks at Epic know they're doing it all wrong with Unreal Engine 3 then. And pretty much every other retail game I know of.
I'm pretty sure Dead or Alive uses Cas' method though. Seeing as you can't play the game over here unless you have a tv that will do 60hz.
Fortunately 99.99% of TVs do 60Hz automatically so they can sell them in other markets without adjusting the design.
It all goes out the window when you start doing things in 3D or over a network of course. But a great place to start is a 60Hz logic loop and 60Hz render loop :cool:
Cas :)
>Actually I've never used Java2D for anything other than GUIs so I don't have a
>clue how it works.
Lies. :P
Wasnt the first incarnation of puppytron a j2d game? I remember your rantings about its random "no sir, I wont accelerated that"-behaviour. And I also remember that you chimed in in one of those j2d/windowed/vsync hackery threads. Like there is some odd dx call for that kind of thing. (Well, its like 3 years ago... excuse the lack of details.)
>But even nvidia cards lie about whether vsync is enabled or not because the
>user can force it off in the control panel.
Last time I checked that (~2 years ago) it worked perfectly fine with all 4 settings.
Setting swapinterval to 1 and then obtaining the current value gave me:
always on - 1
on by default - 1
off by default - 1
always off - 0
And setting it to 0 and getting the current value gave me:
always on - 1
on by default - 0
off by default - 0
always off - 0
The same with an ati card resulted always in 0.
>Fortunately 99.99% of TVs do 60Hz automatically[...]
So far I havent seen a tv which cant do pal60 (aka PAL-60/525 aka PAL-M). However, with tv-out its a different thing. My card for example cant do that (its a shame really), but there are some indicators (ati tray tools) that this isnt generally true for ati cards.
Rainer Deyke
05-20-2006, 09:34 AM
Better let the folks at Epic know they're doing it all wrong with Unreal Engine 3 then. And pretty much every other retail game I know of.
Since Unreal Engine 3 (presumably) has network play support, it probably uses method #2 or #4. (Either that, or it has a problem with network games becoming desynchronised. Or a pure client-server architecture for network games, but this seems unlikely due to the latency involved.) Nonetheless, if I had a refund for every for every timing bug I encountered in a commercial game due to use of #3, I would significantly more money than I do right now.
luggage
05-20-2006, 09:53 AM
No. Unreal Engine 3 uses a delta method - trust me.
Because some coders struggle with using delta doesn't mean the method is bad. It's just bad coding - you can get timing bugs if you're a bad coder no matter which method you use.
And another note. Network games getting desynchronised? All network games are desynchronised now. Can't remember the last network game that required it to be in sync.
princec
05-20-2006, 10:38 AM
No. Unreal Engine 3 uses a delta method - trust me.
Because some coders struggle with using delta doesn't mean the method is bad. It's just bad coding - you can get timing bugs if you're a bad coder no matter which method you use.
And another note. Network games getting desynchronised? All network games are desynchronised now. Can't remember the last network game that required it to be in sync.
I think Tribal Trouble is synced. (Similar to Diablo?)
Cas :)
I think Tribal Trouble is synced. (Similar to Diablo?)
Cas :)
I think he means he can't remember the last FPS that was synced. Most RTSs are synced, so Tribal Trouble is not a surprise.
Rainer Deyke
05-20-2006, 03:54 PM
Because some coders struggle with using delta doesn't mean the method is bad. It's just bad coding - you can get timing bugs if you're a bad coder no matter which method you use.
Delta-time is an inherently flawed technique. A good coder can work around a flawed design to some extend, but a competent coder will not choose a flawed design in the first place.
And another note. Network games getting desynchronised? All network games are desynchronised now. Can't remember the last network game that required it to be in sync.
"Desynchronised" in the sense of "the game state on one computer is (significantly) different than the game state on another computer"? People in a deathmatch getting kills on their local computer while their opponent successfully dodged the attack on their computer (without retroactive correction)? I'm going to assume that you don't actually mean that.
luggage
05-20-2006, 04:24 PM
You keep saying it's inherently flawed, yet the majority of retail games use this technique. Cutting edge development like Unreal Engine 3 does - if it's so wrong then why haven't they dropped it? Why are they writing one of the most advanced game engines, which they'll license for a truck load of cash incidentally, and using a technique which you say won't work?
You said a problem with the delta system is network games becoming desynchronised. Network games aren't realy synced any more, everyone sees something slightly different. So why would a delta system not work? We're past the stage where you send keypresses to each of the machines playing.
PeterM
05-20-2006, 04:42 PM
I suspect most network games have a fixed server update rate with a variable client update rate. Obviously there must be sync problems involved, but it looks like they get taken care of without anyone noticing.
Rainer Deyke
05-21-2006, 01:14 AM
You keep saying it's inherently flawed, yet the majority of retail games use this technique.
Basically your arguments amounts to "everybody is doing it", while failing to address my technical arguments at all. Large game studios do all kinds of stupid things, and commerical games regularily ship with serious bugs. Even the mainstream software development is generally ahead of the game industry in terms of development practices.
Cutting edge development like Unreal Engine 3 does - if it's so wrong then why haven't they dropped it? Why are they writing one of the most advanced game engines, which they'll license for a truck load of cash incidentally, and using a technique which you say won't work?
It clearly does "work" in the sense that you can write a more or less playable game despite the flaws of the technique. I have higher standard of software engineering than that.
Rainer, people have addressed some of your points already in this thread. It's great that you strive for this higher standard of software engineering, but you can really only say that if you are in a tiny sandbox where the simulation is all that matters. Soaking up CPU time to the point of inefficiency and/or buffering a crapload of frames could be seen as "fundamentally flawed" in the right context. I.e. everyone is making compromises, even you.
Since it sounds like you are obviously more experienced than I am with this sort of thing (I'm serious; not being patronizing or sarcastic), can you give your opinion on the method PeterM/Fabio suggested in this thread? It sounds like the way to go, given my needs. I welcome any caveat warnings.
NuriumGames
05-21-2006, 03:47 AM
For BreakQuest I used #2 for physics/collisions, #3 where possible for example all particles code (also used integer math here), and finally a low latency timer (10 fps) for game events that do not need more than that.
Objects can be dynamically added/removed from a bunch of lists and are processed as required (preFrame, postFrame, highFrequency, lowFrequency, ...).
I'm sticking twith this scheme.
PeterM
05-21-2006, 03:55 AM
By the sounds of it, timing is one of those Holy War issues :o
Fabio
05-21-2006, 04:42 AM
Perhaps if we merged this thread with "Who is who" it would gain authoritativeness. ;^)
I am...
:D
so I claim...
:eek:
"Ouch!"
Jamie W
05-21-2006, 06:00 AM
I'm interested in using either #1, or #2, for my current game. It's 2d, and I hate all this delta time nonsense.
I'm quite sure #2 would run very smoothly; I had planned on updating my game physics in 1ms increments, so I emtimate anywhere between 10 and 17 game physics updates for every render. So for each game render the number of times I call the game physics would be something like (in case of 60hz screen refresh): 16,17,17,16,17,17,16,17,17,17,16,17,17,16,17,17, ....
Because of the small (1ms) time slice for each physics update, the movement won't look choppy.
I had also thought about doing some (physics related) things, only once every 4, or 8, calls to the physics update function, and calculation of which animation frame to render could be done once per frame update (render).
I'm also curious about option #1 ...
Being an idiot I stick with #1 (and preferably with Vsync on). My game logic is utterly trivial and uses almost no CPU, and I simply design the games to run at 60fps on the minimum spec. So easy it hurts. And always silky smooth.
Cas :)
What's your experience been with #1? If the player has his monitor running at 80hz say, would the game just run a bit faster? If it was set at 120hz, it would run twice as fast? Or am I missing something? For me, this is the core issue with #1; getting my game to run at same speed, no matter what the monitor frequency.
Also, what's the reliabilty of forcing the monitor frequency to 60hz?
The issue of windows freezing up or stalling, doesn't bother me too much. I wouldn't want to set up a situation, where my game stops rendering, for lets say one second (while windows 'hiccups'), and then the action suddenly jumps forward one second, with the player having no control or interation with the game for that one second. That's just ugly. I would prefer the game to just halt for a second, while windows gets it's act back together again.
Also, if your game goes on XBox live arcade, would there be a problem with using #1?
Thanks.
Speckled Jim
05-21-2006, 06:18 AM
I've used various strategies over the years, including just using the vsync on consoles to provide timing which is fine if you can guarantee your code will run in a frame.
But for general work I use delta timing. As long as you are sensible, the results for most game code will be more than sufficient. All game coding is about compromise anyway, there seems little point in getting on your high horse about one aspect of it. For the most part in games if it looks right, that is usually good enough.
princec
05-21-2006, 06:18 AM
What's your experience been with #1? If the player has his monitor running at 80hz say, would the game just run a bit faster? If it was set at 120hz, it would run twice as fast? Or am I missing something? For me, this is the core issue with #1; getting my game to run at same speed, no matter what the monitor frequency.
Also, what's the reliabilty of forcing the monitor frequency to 60hz?
Been using #1 since the dawn of time. Monitor can nearly be switched to 60Hz. I ask afterwards whether the monitor is indeed running at 60Hz and if it says yes, I turn vsync on as well. Lastly I cap the frame rate with a hires timer at 60Hz either way, which means drivers can't lie to me about the monitor rate and get away with it :)
The great bit about #1 is that a game loop looks like this:
while (!finished) {
for (Entity e : entities) {
e.tick();
}
for (Entity e : entities) {
e.render();
}
swapBuffers();
syncTo60Hz();
}
no crazy floats, no deltas, no worries. Like I say, I'm an idiot and can't cope with complicated code when I just want some sprites to whiz around in a reliable sort of way.
Cas :)
Jamie W
05-21-2006, 06:35 AM
Thanks Cas.
The simplicity of #1, very much appeals to me. I'm just concerned, thinking it must be too good to be true, and what's the catch, or drawbacks with it etc?
If you're requesting the monitor to go to 60hz, and it doens't, but you're still updating your game physics at 60hz, doesn't that make the action 'choppy'? Has that been an issue for you?
Fabio
05-21-2006, 06:43 AM
I'm interested in using either #1, or #2, for my current game. It's 2d, and I hate all this delta time nonsense.
I don't understand the link between "delta time" and "nonsense", but I'm guilty of not wanting inefficient code that even chops..
princec
05-21-2006, 06:47 AM
Thanks Cas.
The simplicity of #1, very much appeals to me. I'm just concerned, thinking it must be too good to be true, and what's the catch, or drawbacks with it etc?
If you're requesting the monitor to go to 60hz, and it doens't, but you're still updating your game physics at 60hz, doesn't that make the action 'choppy'? Has that been an issue for you?
The catch is you are restricted to designing your game around a 60Hz tick rate with not much scope to change that afterwards should the need arise. I like restrictions like this though, as they help me focus.
The other catch is that for true 3D games it's not a good method. The brain processes depth information in a completely different way to panning motions. For a 2D game, ie. one where the fundamental gameplay is in two dimensions not necessarily the renderering - the brain much, much, much prefers that the action slow down and every frame is rendered one at a time rather than suddenly warping. For 3D the exact opposite is true, by and large. As you're doing 2D though it's a good choice, IMHO.
To see what a 60Hz game looks and plays like when the monitor's at 85Hz, try one of mine in windowed mode.
Cas :)
luggage
05-21-2006, 06:51 AM
Rainer: Your techincal problems have been addressed by others - I didn't feel the need to go over that ground again.
Jamie W
05-21-2006, 07:22 AM
I don't understand the link between "delta time" and "nonsense", but I'm guilty of not wanting inefficient code that even chops..
Hi Fabio,
Me too! I'm guilty of not wanting inefficient code that even chops; yet I have no problem understanding the link between "delta time" and "nonsense".
:p
Seriously though, for a 3D game, it's all well and fine. For a 2d smooth arcade style game, I personally wouldn't use it. For one, I just don't like the idea of factoring in a 'delta time' in to all game object movements. It's adding more complication to my code, and I feel the time and energy spend doing so, would be better used elsewhere. That's just my personal preference and feeling though, no doubt others will have a different view (and you're all wrong ... haha).
Anthony Flack
05-21-2006, 07:26 AM
The idea of turning every integer ticker and counter into a floating-point hairball is enough to put me off delta time. I use a lot of simple integer counting variables.
Jamie W
05-21-2006, 07:34 AM
The catch is you are restricted to designing your game around a 60Hz tick rate with not much scope to change that afterwards should the need arise. I like restrictions like this though, as they help me focus.
You don't have any problem with your game running faster than you intend, on some systems?
What percentage of your users, do you think play your games faster than the intended 60hz? What's your feeling on this?
I've played your titan attacks and robotron games, both work fine (very smooth) in fullscreen and in windowed mode, my LCD is set at 60hz anyway, and I can't set my LCD to anything but 60hz. Is that standard with LCD displays? Are they all 60hz?
Mike Boeh
05-21-2006, 07:51 AM
A lot of the time, a simple 60hz timer would work... But there are a couple problems....
It won't be smooth in windowed mode (the other three methods will)
When changing the sync of the monitor, the screen sometimes won't be centered. I used to get a lot of tech support emails about this one.
This may not be a problem, but how often do you actually get the hz you request?
#2 usually produces smooth results, and is very nice for doing simple, accurate collisions. But it's also the least efficient. The thought of having to account for time in my logic loop really puts me off to #3...
I guess there is still no single method that's best. I was thinking of writing a demo that does all 4....
luggage
05-21-2006, 07:51 AM
The idea of turning every integer ticker and counter into a floating-point hairball is enough to put me off delta time. I use a lot of simple integer counting variables.Timers have to be floats, I usually do the following...timer = 2.0f; // delta is in seconds so this will be a 2 second timer.then in the update...timer -= delta;
if (timer <= 0.0f)
{
// timer is up.
}
Speckled Jim
05-21-2006, 08:08 AM
The idea of turning every integer ticker and counter into a floating-point hairball is enough to put me off delta time. I use a lot of simple integer counting variables.
It's no more complicated though, just a different way of thinking about it. If you are using integer counters now to track time based on a certain discrete timestep, then that is arguably more complicated then just being able to check for reaching a specific time directly, ie 4.5 is 4.5 seconds, instead of a count of 270 using a 60hz timer.
princec
05-21-2006, 09:54 AM
A lot of the time, a simple 60hz timer would work... But there are a couple problems....
It won't be smooth in windowed mode (the other three methods will)
When changing the sync of the monitor, the screen sometimes won't be centered. I used to get a lot of tech support emails about this one.
This may not be a problem, but how often do you actually get the hz you request?
#2 usually produces smooth results, and is very nice for doing simple, accurate collisions. But it's also the least efficient. The thought of having to account for time in my logic loop really puts me off to #3...
I guess there is still no single method that's best. I was thinking of writing a demo that does all 4....
Hm, maybe because you started a few years before me... but I've never ever had anyone drop me a line because their monitor's displayed the picture in the wrong place. I know they do it because I've seen it myself but still for some reason no-one's seen fit to email me.
I've no idea how often I get the frequency I request but I suspect it's close to 100% of the time.
Also, my games run perfectly smooth in windowed mode (and always at 60Hz) using a high-res timer to cap it within 1ms accuracy. Or at least so smoothly you can't tell, and that's the desired effect!
Cas :)
[...]
The other catch is that for true 3D games it's not a good method. The brain processes depth information in a completely different way to panning motions. For a 2D game, ie. one where the fundamental gameplay is in two dimensions not necessarily the renderering - the brain much, much, much prefers that the action slow down and every frame is rendered one at a time rather than suddenly warping. For 3D the exact opposite is true, by and large. As you're doing 2D though it's a good choice, IMHO.
[...]
It isnt really a matter of 2d vs 3d imo. Its how much of the screen changes, how fast and the strength of contrast.
First person shooters for example are pretty much the worst case scenario. The whole screen changes all the time and you can even see tiny differences between 2 different jump height rounding methods at 85fps@85hz. (That really surprised me actually.)
And on the other side of the spectrum are colorful 2d games w/o scrolling.
But I agree that this simple method seems to be just fine for 2d games... even with rather fast 2d scrollers you dont see much of a difference (because its still relatively slow even if it feels sorta fast).
[...]
You don't have any problem with your game running faster than you intend, on some systems?
[...]
The loop is backed up by a frame cap method, which tries to limit the minimum time per frame to 16 msec (- last frame catch up), which in turn means that the maximum framerate is 62.5fps (if vsync is disabled).
The only issue you have are slowdowns on systems, which dont meet the minimum system requirements (just keep em low) or those other weird cases with 50hz or 55hz tfts (they are pretty rare) or well... that thing I mentioned before (ati + tv-out enabled + pal + vsync = 50fps max).
Jamie W
05-21-2006, 12:00 PM
OK, we're still talking about #1 here oNyx? (and I agree it's probably more suited to 2D arcade games).
The issues I can see with it, are:
1. If you code your game to assume a 60hz update, and a user has say a 75hz display, the game will speed up.
2. If you cap your game to avoid this speeding up, the movement of your game objects (and scrolling) will appear 'choppy'.
The above (2) assumes fullscreen mode using vsync, it sounds like Cas doesn't have too many problems with his game using #1, in windowed mode.
Capping comes in to play on (the very few) systems that fail to go in to 60hz on request, is that correct?
Rainer Deyke
05-21-2006, 12:09 PM
Since it sounds like you are obviously more experienced than I am with this sort of thing (I'm serious; not being patronizing or sarcastic), can you give your opinion on the method PeterM/Fabio suggested in this thread? It sounds like the way to go, given my needs. I welcome any caveat warnings.
If you use method #3 (i.e. delta-time), you will experience slight variantions in the game simulation each time you run the game. This is unavoidable. If you find this acceptable, go for it. If you choose method #4 (or #2 or #1) instead, you gain the following benefits: You can record the input and play back the game simulation exactly, which is very valuable for debugging and can also be used for other uses (i.e. attract mode, instant replay).
If you have a networked mode, you can make sure that variations in the game simulation between different computers on the network are kept at an absolute minimum.
You get to factor out the timing code from the game simulation. Once the timing code works, you never have to touch it again and you will never experience another timing bug.
You don't have to worry about the magnitude of the variation between slow computers and fast computers, because there isn't any. You don't have to worry about setting the upper and lower limit of the time delta, because there isn't any. You don't need to worry about the effects of erratic time deltas on the numerical stability of your simulation. Everything just works.
You get the personal satisfaction of knowing that your game isn't just sufficiently but absolutely independent of computer speed.
>OK, we're still talking about #1 here oNyx?
Yes.
>1. If you code your game to assume a 60hz update, and a user has say a
>75hz display, the game will speed up.
You need to back it up with a framecap. There is no guarantee that you can pick a 60hz mode and there is also no guarantee that you can enable vsync (a driver-sided "always off" overrules everything).
>2. If you cap your game to avoid this speeding up, the movement of your
>game objects (and scrolling) will appear 'choppy'.
Yes. But it wont be that visible. (It is pretty visible with a white rect on black background tho.)
>Capping comes in to play on (the very few) systems that fail to go in to
>60hz on request, is that correct?
Yes. And if you cannot enable vsync (or more generally if its set to "always off").
TheMysteriousStranger
05-21-2006, 12:35 PM
If you use method #3 (i.e. delta-time), you will experience slight variantions in the game simulation each time you run the game
That's the whole point of delta. Computers do not run perfectly at the same speed all the time - other tasks like to try and steal your game's cpu time. Delta timing is designed to incorporate those slight variations into the game updates, removing any problems with the game update not running at the required speed.
You can record the input and play back the game simulation exactly, which is very valuable for debugging and can also be used for other uses (i.e. attract mode, instant replay).
Care to explain to Id then that their Q3 engine (which uses delta timing) isn't recording the input for demo playback? I have recorded demos myself in Q3 engine games and it seemed flawless to me.
If you have a networked mode, you can make sure that variations in the game simulation between different computers on the network are kept at an absolute minimum.
If synchronisation is that important to your game (a factor that is less important since broadband became the norm for online gaming), then you can seperate game logic and network timings, and simply send timescale data along with the update data from the server, making it possible to sync the client to the server.
You get to factor out the timing code from the game simulation. Once the timing code works, you never have to touch it again and you will never experience another timing bug.
It's still possible to make timing based bugs in non-delta systems. It's all about testing/bug fixing until your game no longer has those bugs.
You don't have to worry about the magnitude of the variation between slow computers and fast computers, because there isn't any. You don't have to worry about setting the upper and lower limit of the time delta, because there isn't any. You don't need to worry about the effects of erratic time deltas on the numerical stability of your simulation. Everything just works.
You seem to have missed the entire point of delta timing systems - with delta, the time difference can be small or it can be huge - the game will still work EXACTLY the same. If it doesn't work properly, it's the dev's fault for making a lazy implementation of delta, it's not a flaw in delta timing systems. A good delta implementation is able to work with erratic timing - it's expected.
You get the personal satisfaction of knowing that your game isn't just sufficiently but absolutely independent of computer speed.
This doesn't even make sense. Delta timing is completely independant of the system speed - the whole point of basing movement/updates in delta timings is to seperate the game updates from the speed of the system.
luggage
05-21-2006, 12:50 PM
What if the bottleneck on a slow machine is the CPU? And your logic won't run at 250-1000 fps? What do you do then? Drop your logic and then go back through your entire game adjusting your timing values?
You get several nice "pros" when you use a delta system...
* It's an absolute piece of cake to move to other timing systems.
* You can do super smooth slow motion and bullet time effects.
* You can speed your game up for testing or put "hyperspace" effects in for free.
* You can still record games for debugging. Just dump out the delta at the same time. Easy.
* You get a pause mode for free.
* You get the "personal satisfaction" of knowing your code isn't inefficient.
* You get the "personal satsifaction" of knowing you're not causing laptop batteries the world over to run out long before it should.
* Working out how long a wait is is easier.
* You can stick to Standard Units. 1.0f = 1 meter. 1.0f = 1 second. I want to move at 10 metres per second? x += 10.0f * delta;
* You get to be able to draw more things as you're not wasting CPU time.
* You don't have to worry about slow CPU's causing your game to bottleneck.
I can't be bothered to do any more but it's easy to find pro's if you look hard enough for any of the methods. The whole point of this discussion is that there are several methods all will work and all have their pro's and con's. You keep saying delta is flawed but that "flaw" can be fixed with...if (delta > 0.5f)
{
delta = 0.5f;
}before you call any of your updates. Job done. Never have to worry about it again. And the day a render takes no clock cycles is the day I'll worry about my delta being zero.
Slight variations in the game simulation do not matter. In fact, the player will probably get slight variations in what they see no matter which method you use.
PeterM
05-21-2006, 12:52 PM
To (hopefully) clarify the issue for FPS engines:
Engines like Quake 3 often use a fixed server logic update rate, but that rate is admin-tweakable. So the movement uses delta-time, since it doesn't know ahead of time what the update rate will be. On the server it will be fixed, on the client it will be variable.
Mike Boeh
05-21-2006, 01:35 PM
I just tried Titan Attacks windowed... It's not silk smooth because I run at 100hz desktop... But most gamers would probably never notice the difference anyway, so there's really nothing wrong with using that method.... (EDIT: oh and it did take my monitor to 60 hz fullscreen)
I got collisions going perfectly with #4, so I am sticking with it for now... No latency that I can perceive, and I am a really big stickler for that kind of thing :)
But in reading all the opinions here, it seems like there are really valid pros and cons to each way....
If you use method #3 (i.e. delta-time), you will experience slight variantions in the game simulation each time you run the game. This is unavoidable. If you find this acceptable, go for it. If you choose method #4 (or #2 or #1) instead, you gain the following benefits:
Good points. The reason I'm asking is because the technique in question (linked by PeterM earlier: http://www.gaffer.org/articles/Timestep.html) actually appears to be a hybrid of #3 and #4. It accepts delta time as input but processes the simulation at fixed timesteps and tweens with the previous frame. So in theory you get fixed timesteps with better CPU load balancing. I'm just wondering if I'm missing something obvious :D
Mike Boeh
05-21-2006, 01:57 PM
To (hopefully) clarify the issue for FPS engines:
Engines like Quake 3 often use a fixed server logic update rate, but that rate is admin-tweakable. So the movement uses delta-time, since it doesn't know ahead of time what the update rate will be. On the server it will be fixed, on the client it will be variable.
The physics for these games happen on the server right?
Mike Boeh
05-21-2006, 02:01 PM
Good points. The reason I'm asking is because the technique in question (linked by PeterM earlier: http://www.gaffer.org/articles/Timestep.html) actually appears to be a hybrid of #3 and #4. It accepts delta time as input but processes the simulation at fixed timesteps and tweens with the previous frame. So in theory you get fixed timesteps with better CPU load balancing. I'm just wondering if I'm missing something obvious :D
I read it as straight #4...
The solution is to interpolate between the previous physics state and the current state based on how much time is left in the accumulator. This will add a latency of up to dt to your physics simulation, but the visual results are definitely worth it. Here is how to implement it:
PeterM
05-21-2006, 03:42 PM
I think it's interpretable as either 3/4 or 4, since they aren't mutually exclusive.
Larry Hastings
05-21-2006, 04:48 PM
Quake 3 used #3. I gather the game had a pretty simple approach: compute game state, render frame, forever. So if you got 120fps, you were getting 120 game state updates per second too. Some l33+ players discovered that there were some otherwise-unmakable jumps in the game that you could make, if your computer was running within a specific range of FPS. Thus giving advantage to some players over others.
For that reason, Carmack changed Doom 3 to use #2: a strict 60fps game state clock. If you render Doom 3 at 100fps, 40 of those frames are redundant.
My game also uses #2, at 120fps. I worked very hard to get the game to be 100% repeatable from recordings of just the inputs, and I'm happy to say that I've succeeded. If I'd used #3, I simply wouldn't have been able to achieve it... or at least without the frame rate itself becoming an input. I would definitely consider #4 if the game state were slow to calculate, but I don't expect to have that problem any time soon.
Edit: I also wanted to mention that I chose 120fps because 120 is higher than anyone's frame rate is likely to be, and it's such a wonderfully composite number. 2 x 2 x 2 x 3 x 5. If you run at 60fps, or 80fps, or 100fps, the game state updates will coincide nicely with screen updates I figure. It probably makes little or no difference, as almost any number > 100 would work fine, but perhaps there is a tiny advantage to a good composite number.
luggage
05-21-2006, 05:12 PM
Quake 3's problem was rounding errors if I remember correctly. They clamped the velocity vectors to an int. A poor implementation.
If the update is limited to 60fps and you're rendering at 120fps won't it look juddery as half of your frames are the same?
Rainer Deyke
05-21-2006, 08:29 PM
This doesn't even make sense. Delta timing is completely independant of the system speed - the whole point of basing movement/updates in delta timings is to seperate the game updates from the speed of the system.
Um. You are aware that, with floating point variables, moving an object by 0.1 units 100 times does not yield the same result as moving it by 0.2 units 50 times, right? This is pretty much fundamental to the floating point mathematical model. (A quick check using Python yields 9.9999999999999805 for the former and 9.9999999999999964 for the latter. With single-precision floats, the difference will be much larger.)
Now, you could stick to fixed-point/integer math, and you could regularily round your variables to eliminate rounding artifacts, but it is highly unlikely that you will be able to eliminate all timing artifacts for any but the simplest games.
Rainer Deyke
05-21-2006, 08:46 PM
You get several nice "pros" when you use a delta system...
* You get the "personal satisfaction" of knowing your code isn't inefficient.
* You get the "personal satsifaction" of knowing you're not causing laptop batteries the world over to run out long before it should.
Actually delta-time is significantly less efficient than method #4 (fixed update rate plus tweening). It requires one physics update per rendered frame, and the actual updates are slower.
You keep saying delta is flawed but that "flaw" can be fixed with...if (delta > 0.5f)
{
delta = 0.5f;
}before you call any of your updates.
That does not address any of the flaws that delta-time is likely to encounter during normal operation. It just keeps one of the most degenerate manifestations of those flaws from manifesting.
And the day a render takes no clock cycles is the day I'll worry about my delta being zero.
Small numbers don't have to be zero in order to cause floating point underflow or in order to disappear entirely when added to a larger number. (Personally I have gotten actual zeros as time deltas before, but only because I use a millisecond timer (with over 1000 fps).
luggage
05-21-2006, 09:50 PM
If I draw something at 9.9999999999999805 and 9.9999999999999964 I bet you couldn't tell the difference on screen.
I never said method 3 is the most efficient, it's just not inefficient. In fact, I never said method 3 is the best at all, I just disagree with you when you say it's flawed and shouldn't be used. There's enough real world applications of the method that show it does work. It's an incorrect message to send out to the folk reading this who aren't sure. Each method has it's pros and cons, you still haven't answered what happens in the other methods if the bottleneck is in your update?
I'm still not sure how you'd get a zero time delta unless you're using an inaccurate timer. Even if you were drawing nothing at all you'd struggle. And in which case who cares? I was under the impression high resolution timers match the clock frequency of the cpu. Therefore your render would have to consist of a NOP and that's it to maybe cause a problem.
I wish you'd explain what these flaws are - your points have been addressed. I'm interested to know if any retail games have managed to work around them. Give me a real world example of where it will matter. I've yet to see these flaws manifest themselves.
Fabio
05-21-2006, 11:56 PM
If you use method #3 (i.e. delta-time), you will experience slight variantions in the game simulation each time you run the game. I really wonder why lotsa people here still don't realize that delta-time can be an integer multiple of a base time (preferably the video refresh period). Thus delta-time can indeed reproduce the same identical results each time it runs, and doesn't necessarily need floating point at all. On the Amiga I wasn't using floating point, trust me, and my games had loooooong demo modes where my previously recorded input was simply coming from memory rather than from the joystick. Never missed one micron all the times it was replayed.
This thread is really becoming a boring religious thread.. with people sticking emotionally on their beliefs instead of wanting to consider simple and proven facts.
On single-player games I use delta-time + one or more steps per frame (as required e.g. by the collisions system) because it is senseless to compute more than the user can see anyway, it's only a waste of processing power, it's not good coding practice, nada-nada-nada. The steps can be linear (floating point is more comfortable/easy), or integer submultiples of a whole frame (e.g. two steps, one 1/8th ahead and the other 1/24th ahead.. that's how I was doing in integer math on the 68000 CPU).
Also, you get the benefit that once you've your physics working with any delta, you can be more sure it's bug free than if it's a tweaked cheat running at a fixed frequency, something that often masks malfunctions that then appear when you never expect them and you've already released your product. If numerical stability is a problem, don't use Euler^H^H^H^H^H^H^H^H^H^H.. :D then do n necessary steps per frame and you're done, or improve your algorithm (use e.g. RK4 integrator or some other solutions).
I.e. on singleplayer I use basicly #3.
On multiplayer, networked games, I prefer a server-clients approach: the simulation runs on the server, and the clients are simply more or less stupid terminals sending their input to the server and displaying what the server sends back (i.e. what each client has in view, no more than this, to avoid bandwidth waste), interpolating the world on the client to simulate a higher frame rate. I.e. basicly #4.
This has proven the best compromise for networked games, but adds undesired latency and other problems, so is far from being ideal as the singleplayer solution, and shouldn't be used also for that.
For why even properly coded delta-time sometimes chops too, check my long post (http://forums.indiegamer.com/showpost.php?p=94098&postcount=9), it's due to unforeseen delays in the renderer, and is common to all methods (which have other added problems as well that increase chopness. Delta-time is the best of all for singleplaying, and I fail to see where it's supposed to be more complex than the other methods. Because you've to factor in one more variable vs fixed-time? Now come back and tell me if it's better this way or the fixed way when you start to deal with collisions and impulses anyway..).
dxgame
05-22-2006, 12:06 AM
I think most Delta Time coders started designing their game or engine tools with the idea of using Delta time from the start. Going from frame based or fixed logic speed and then upgrading :D to delta time based movement can be a bit daunting, but once you code it....correctly, it works flawlessly.
But otherwise, with games....if it works....it works. There are no "correct" ways to code anything, especially on the PC. ;)
Fabio
05-22-2006, 12:35 AM
When I had to adapt my singleplayer code to multiplayer it was a zero-seconds job. I know it wouldn't have been the same the other way round. And what if you change your mind about the Hz to use? You can use #defines to optimize your code in case you want to fix the rate, but your source should always be as much versatile as possible. Anyway, I'm not generally in favour of floating point, expecially now that 64bit integer math is quite viable.
Sharpfish
05-22-2006, 01:49 AM
I think most Delta Time coders started designing their game or engine tools with the idea of using Delta time from the start. ...but once you code it....correctly, it works flawlessly.
Yeah. And if you are using classes then typically you are typing one set of extra '*td' on movement code for example and then forget about it forever. Each object will work from your timer+deltatime algorithms and it doesn't need too much thinking about once those classes are up and running. In my experience it has been the case anyway and it's not too tricky if you designed it from the outset to work like that. :)
Larry Hastings
05-22-2006, 03:42 AM
Quake 3's problem was rounding errors if I remember correctly. They clamped the velocity vectors to an int. A poor implementation.Yes, clearly the problem was rounding errors. Controlling the FPS was what let you influence the rounding error one way or another to your advantage.
If the update is limited to 60fps and you're rendering at 120fps won't it look juddery as half of your frames are the same?No more juddery than playing the game at 60fps.
In point of fact, the Doom 3 rendering engine was capped at 60fps too, because there is no point in rendering redundant frames. Quoting from Carmack on the subject (indirectly through IGN (http://pc.ign.com/articles/456/456054p1.html)):
The game tic simulation, including player movement, runs at 60hz, so if it rendered any faster, it would just be rendering identical frames. A fixed tic rate removes issues like Quake 3 had, where some jumps could only be made at certain framerates. In Doom, the same player inputs will produce the same motions, no matter what the framerate is.Also, the online forum at Beyond3D (http://www.beyond3d.com/forum/archive/index.php/t-7314.html) discussed the high-framerate jumping in Quake 2 and 3.
Jamie W
05-22-2006, 04:06 AM
This thread is really becoming a boring religious thread.. with people sticking emotionally on their beliefs instead of wanting to consider simple and proven facts.
I think we will always have some tendency to do this; our habits and ways of doing things become entrenched, and we loath to leave them behind, esp. when we've found they worked in the past. It's often easier to just defend your own personal view / position, than it is to be open and consider the merit of what other people are suggesting (when it differs to your own view).
I very much think (and it's been said repeatedly already) that there's no such thing as wrong or right, it's just a matter of which approach is the most appropriate for your game, and also for you personally as a coder.
I favour the non delta time approach, but then my background isn't in PC game dev (with all it's non-standard frame rates). I may change my view on this further down the line.
I try to consider all the implications of using each approach, and for the type of game I'm making (I'm considering using method #2), I believe running my game logic 10x more often than I render my game, would take CPU usage from 0.1% to 1% (if that) for computing my game state. I'm quite happy with this trade off against not having to complicate my code by factoring in delta time.
If my game was a more sophisticated, it may well be a different story. Been a good thread though! (but getting a bit boring now).
luggage
05-22-2006, 05:27 AM
I very much think (and it's been said repeatedly already) that there's no such thing as wrong or right, it's just a matter of which approach is the most appropriate for your game, and also for you personally as a coder.Spot on. It's interesting how all the methods have their pro's and cons. One thing is for sure, all the methods will work if you implement them correctly and there doesn't seem to be one way which is better than the rest no matter what. Just choose what's best for you.
Fabio
05-22-2006, 06:15 AM
Spot on. It's interesting how all the methods have their pro's and cons. One thing is for sure, all the methods will work if you implement them correctly and there doesn't seem to be one way which is better than the rest no matter what. Just choose what's best for you.
Each one has its pros and its cons, true, but some chop more than others though.. this is unfortunately an undeniable fact.
Anthony Flack
05-22-2006, 08:26 AM
It's no more complicated though, just a different way of thinking about it. If you are using integer counters now to track time based on a certain discrete timestep, then that is arguably more complicated then just being able to check for reaching a specific time directly, ie 4.5 is 4.5 seconds, instead of a count of 270 using a 60hz timer.
Yeah, I know I could make it work, but I use so many little timers for widdly little animation details that would be just more of a pain to set up that way. And since I have so many, I prefer the shorter way. I like using timers that trigger a bunch of discreet, single events as they count down.
I do have one animation effect which is wired directly to the computer's clock, though - lip syncing the dialogue.
I was going to mention the replay thing, but I guess everyone has their methods of getting around it. I like being able to just record the inputs and the random number seed and get a painless playback - except it's never quite painless because I have a bad habit of putting random number rolls into my rendering routine, which ruins everything...
I've not found any problems with inefficiency of over-processing logic loops, even though I was worried about it. On my (hardly state of the art) computer, my logic never seems to take up more than 1-2ms per frame, and that's with a fair bit going on. Of course, your results may vary, and I guess if I was concerned that I'd be doing a lot of number crunching I might go with a tweening method.
I guess delta does give a good degree of flexibility with the timing, too. I have a speed slider in my game, but it's limited to running in discreet steps of logic loops to rendered frames.
gosub
05-22-2006, 11:04 AM
I'm using a variation on #4, and I'm not seeing any of the CONS you mentioned. The variation is that I have an events timer which allows events to be scheduled at any time (to the nearest millisecond). Just before rendering, the physics engine processes all events up to the current time. Rendering is completely separated from physics (including collision detection), and the game doesn't have a clue when a frame is being rendered.
For hit detection, I have an event which executes exactly* every 20 milliseconds**, and detects collisions very precisely and deterministically***. Game objects follow some kind of path (hand drawn, linear, accelerated, etc.) and take no CPU time, except when it comes time to render or run collision detection. For instance, when the collision event (or render) needs to know the position of an object, it just uses a formula like D = 1/2*A*T*T.
So to summarize: I do not have a master loop which requires all events to happen at a specific time and rendering is completely separated from physics.
-Jeremy
* As far as the physics engine is concerned.
** I could just as easily use any timing by changing a single constant. I chose 20 milliseconds because (empirically) it was the longest interval where all collisions were detected properly
*** I can re-run the game to any point in time, and get the exact same game state.
gosub
05-22-2006, 11:19 AM
P.S.
Getting 2 things to bounce off each other properly at 25hz is a real pain! :(
My game currently doesn't need to bounce anything, but if it did, I would probably need to change collision detection to run every (oh say) 5 or 10 milliseconds. This would be very easy, and wouldn't effect the render quality at all.
-Jeremy
gosub
05-22-2006, 11:38 AM
I've been using #2, running at about 300hz...
However, I've never been able to get it properly smooth. Part of the problem is, I think, that using Blitz I only have access to a ms timer, and that doesn't seem quite good enough.
Unfortunately, the standard Windows timer runs at a resolution of 5 milliseconds [edit - or 10 as Larry says] (depending on the version of Windows), which is not good enough to get perfectly smooth frames. When you combine that with 300Hz logic and a 60Hz refresh, I can understand why you're having problems.
The first thing you can try is changing your frame rate to [edit - 200Hz, or something more compatible with Windows]. A better approach would be to use the Windows high performance timer. There are two of them: 1) Multimedia timer (1ms resolution), and 2) Hardware timer (QueryPerformanceCounter).
[edit - removed, possibly incorrect statement]
-Jeremy
PeterM
05-22-2006, 11:49 AM
You can also average the time of the last few frames, but (like everything) that can bring it's own difficulties.
gosub
05-22-2006, 11:51 AM
Even if you have perfect timing and you render perfectly on every single frame, you can still get choppiness. This happens because sound algorithms and other "stuff" happens periodically. It's not long enough to cause a missed frame, but it's long enough to mess up the rendering.
Say you're rendering using a 60Hz monitor (and you have DirectX synched to it). Now collect the difference in time between render frames. You'd expect to always see 16 or 17 milliseconds. Here's what you might see:
16
16
16
27 <--- What happened?
5
16
Some high priority task ran and delayed the start of your render, however DirectX still rendered your frames at the proper time because of the double or triple buffering. I've noticed this phenomenon when using Windows media player to play sound, but not nearly so much when using Bass.
-Jeremy
Larry Hastings
05-22-2006, 02:29 PM
There are four major APIs I could name in Windows to get the time (and various other APIs that seem to be a layer on top of these APIs). A quick summary:
TSC, the Time Stamp Counter, a new instruction as of the Pentium architecture. It tells you how many cycles the CPU has executed since it was powered on.
QueryPerformanceCounter (QPC), the high-resolution timing API in Windows.
timeGetTime() (TGT), the old-school method for reasonably-high-resolution time.
GetSystemTimeAsFileTime() (GSTAFT), with a return type as big as all outdoors. GetTickCount() and the C functions _ftime() and _clock() are implemented using GSTAFT.
Unfortunately these all have their failings. I will save you a lot of headaches and palaver and simply tell you: use QPC.
There are two places where QPC falls down. One is on a specific type of "south bridge" chipset, where a busy PCI bus will cause QPC to leap forward by seconds at a time. This is a well known and acknowledged bug. (http://support.microsoft.com/default.aspx?scid=KB;EN-US;Q274323&) The other is on specific kinds of modern hardware, such as a laptop our own princec has. On computers where QPC is implemented using TSC, and where the CPU supports SpeedStep, the frequency of QPC will change when the CPU frequency changes, (http://forums.indiegamer.com/showthread.php?t=2394) and there's no way of noticing this without a lot of heavy-duty wizardry.
Both these problems are rare, so my advice is use QPC and console your users if they encounter one.
For the record: TSC is fussy because a) you have to time it yourself, b) on CPUs with SpeedStep the frequency will change, and c) on multi-core CPUs, if you don't specify CPU affinity, you'll get different results from the multiple TSC counters. TGT is fussy because a) it's so low-resolution, only 1ms in the best case (using timeBeginPeriod()) and usually not even that good, b) it drifts a little, which Tom Forsyth blames for Startopia games going out of sync, (http://sourceforge.net/mailarchive/message.php?msg_id=2030709) and c) it is slow to call (taking 1-2microseconds to execute). GSTAFT and its ilk are unusable, as they only have 10ms accuracy on the best of days (and only 55ms accuracy on older machines).
1msec isnt really "low". All quake engine based games are using such a timer and its really good enough. Surprisingly.
My machine shows that leaping behaviour. Its pretty annoying if a game has a problem with that (as you can see in that bug listing... one should backup that timing function to detect this kind of bad behaviour).
>GSTAFT and its ilk are unusable, as they only have 10ms accuracy on the best
>of days (and only 55ms accuracy on older machines).
Its actually win9x (and not old machines per se). With 2k/xp its 10msec and linux (and mac?) is 1msec.
If you're writing old java its the only type of timer you have, but it sorta works for method #1 (the other ones too... in theory). I came up with some adaptive yield throttle loop construction which even works reasonable well with a resolution as bad as 250msec. In this year's 4k competition several games were using that method and it worked very well across a broad selection of hardware.
The side effects are (obviously) that it can over/under steer a bit if there are huge performance jumps, but the damping sorts that out for the most part.
Needless to say that its of course a major pain in the rear regardless. A 1msec resolution is damn awesome in comparison ;)
illume
05-22-2006, 04:12 PM
Being an idiot I stick with #1 (and preferably with Vsync on). My game logic is utterly trivial and uses almost no CPU, and I simply design the games to run at 60fps on the minimum spec. So easy it hurts. And always silky smooth.
Cas :)
Hey,
just for your information titan attacks pauses quite frequently on some of my machines.
I think it is because my machine sees a cpu hog an gives it a penalty. Do you add a little sleep between frames?
However, when these slow downs happen the game goes slowly too. Which is nice, rather than the action going on whilst you can't do anything.
dxgame
05-22-2006, 09:38 PM
"There are four major APIs I could name in Windows to get the time.."
hmm.. which one of those is the Multimedia Timer?
Larry Hastings
05-22-2006, 11:49 PM
"There are four major APIs I could name in Windows to get the time.."
hmm.. which one of those is the Multimedia Timer?timeGetTime().
princec
05-23-2006, 02:21 AM
Hey,
just for your information titan attacks pauses quite frequently on some of my machines.
I think it is because my machine sees a cpu hog an gives it a penalty. Do you add a little sleep between frames?
However, when these slow downs happen the game goes slowly too. Which is nice, rather than the action going on whilst you can't do anything.
That'll be because your machine ain't actually fast enough to run it at 60Hz :) Try 16bit desktop colour. That's just the way I deal with slowdowns :D
Cas :)
PeterM
05-23-2006, 02:32 AM
<devil's advocate>
Would that be one implicit vote for not locking the frame rate?
</devil's advocate>
voodooshaman
05-23-2006, 02:56 AM
In the commercial games I've worked on, we've either had no timing strategy at all or everyone has their own little timing strategies for their subsystems. The most used method (up until we moved to middleware) seems to be everyone using their own frame counters to move objects around.
We work with consoles however, but it always amazes me how disorganised and hacked to death commerical code can be. It's amazing it even gets released. Currently, we're using Unreal3, which uses strategy #3 everywhere (at last a strategy to adhere to!).
Fabio
05-23-2006, 03:51 AM
We work with consoles however, but it always amazes me how disorganised and hacked to death commerical code can be. That's probably because the boss wants you to "finish" the work as soon as possible.. and thus one doesn't have the time to produce really well-thought code. This is one of the reasons why I have never worked under anyone, even when I was making retail games.
It's amazing it even gets released. Currently, we're using Unreal3, which uses strategy #3 everywhere (at last a strategy to adhere to!). Someone (certainly not me) said that #3 was more or less an unprofessional shite. Ouch.
princec
05-23-2006, 03:54 AM
<devil's advocate>
Would that be one implicit vote for not locking the frame rate?
</devil's advocate>
Well it would be if my sales were bad but... they're not :cool: and that, at the end of the day, is all that counts!
Cas :)
Savant
05-23-2006, 04:12 AM
Someone (certainly not me) said that #3 was more or less an unprofessional shite. Ouch.
I can certainly see your point, what with Gears of War showing so poorly at E3 this year and practically every game that won an award at the show being an Epic licensee.
Method #3 is obviously not viable.
Fabio
05-23-2006, 04:41 AM
Indeed.. also for the Quake3 engine.. <irony> what a piece of crap smoothness-wise! </irony>
It's about time to close this thread IMHO..
Raptisoft
05-23-2006, 04:43 AM
Am I the only one doing his timing off proton decay?
Savant
05-23-2006, 04:45 AM
It's about time to close this thread IMHO..
I agree. You know, before someone says something stupid.
Fabio
05-23-2006, 04:46 AM
Am I the only one doing his timing off proton decay? Proton decay leads to chopness, due to the quantistic involvement.
You're much better off using General Relativity methods. ;)
voodooshaman
05-23-2006, 04:52 AM
1. Simple fixed rate timerBasically, the game waits for x ms to expire before processing the game loop.Kind of like waiting for VSync with no concurrency between CPU/GPU? Movements calculated using an assumed constant frame-rate and the code hopefully always runs in a frame? Very noticeable when it skips a frame.
2. High frequency internal timer
This is where the game runs internally at, say, 250 fps and will run its game logic the needed amount of times to keep up with the refresh rate.What happens if you're CPU bound and the process loop can barely manage to run in a frame (say 60fps)? You'd be making the game run even slower. I assume movements are calculated using an assumed constant frame-rate and the process-loop is called to keep up with the frame rate? e.g. If we skip a frame, we call the process loop twice? This is fine for consoles, what about PC's with multiple refresh rates? The refresh rate must be a factor in movement calculations.
3. Delta Value Timing ... it means that time is factor in all movement- basically adding another variable to deal with.I'm confused about that quote, surely time is a factor in all animation regardless of the timing strategy? This is the method I'm most familiar with and I like it. I find it the easiest and most flexible to use. It's the only method (as I understand it) that is frame-rate independant. Please correct me if I'm wrong.
4. Low internal fps with tweeningThis is where the game runs very slowly internally, say 25 fps.I've never seen this method used before and don't fully understand it. Perhaps once I do, I'll change my mind from method #3 to #4 ;) Is this method implemented like method #2 but we just render the same frame out again until it's time for an update? Does this mean an assumed constant frame rate?
[Edit - After reading the thread again, most of this has already been covered - sorry. For what it's worth, I think Fabio's arguments are spot on].
Fabio
05-23-2006, 05:05 AM
4. Low internal fps with tweeningI've never seen this method used before and don't fully understand it. Perhaps once I do, I'll change my mind from method #3 to #4 ;) Is this method implemented like method #2 but we just render the same frame out again until it's time for an update? Does this mean an assumed constant frame rate? Basicly you run your simulation/physics_engine/game_logic at a fixed rate, and then freerun your renderer, which will display the physics situation at time-n (n is a fixed delay you can't avoid). This is best done interpolating the two (or more) physical states that surround the particular time you want to display. Of course you've to keep the past x blocks of whole game states as computed by your simulation/physics_engine/game_logic, otherwise your renderer will not know where to find the data it needs.
Basicly it's a fixed rate simulation and a rendering that features sample rate conversion. With sample here I mean a whole simulation/physics_engine/game_logic state (position of each object, etc..).
This method is approximatively as smooth as #3 (approximatively because the smoothness you regain is due to interpolation of objects' positions, etc..), and adds latency too.
Clearly an inferior method than #3 but the best in case of networked multiplayer games for obvious practical reasons due to game clients synchronization.
Mike Boeh
05-23-2006, 07:09 AM
I agree. You know, before someone says something stupid.
People already have, I just deleted them :) Anyway, time for the thread to be closed. It was an interesting discussion though....
vBulletin v3.6.0, Copyright ©2000-2008, Jelsoft Enterprises Ltd.