Delta/Frame Tweening vs. just flip true

Blitz3D Forums/Blitz3D Programming/Delta/Frame Tweening vs. just flip true

trb(Posted 2005) [#1]
Hopefully someone can offer me some advice here. I know the two preferred methods of frame limiting are delta timing and frame tweening. I have used both before and are familiar with the ins and outs of each, and I'm not really happy with either one. When you rip out all the frame limiting stuff and just rely on "flip", everything is smooth as silk.

So what are the downsides of using flip as my frame limiter? I know there's the warning that "some people may disable this feature on their graphics card", but isn't that more of a hardcore gamer thing to do? If my target audience is the casual gamer that probably doesn't do too much fiddling, wouldn't it be reasonable to assume the refresh rate is going to be somewhere in the 60-85hz range and base in game speed off of that?

(I only ask because I recently finished a game that went onto a little compilation CD, and as I was pushed for time did not implement a frame limiter. I figured I could release an updated .exe if there were any complaints, but to date I haven't heard any.)


Anatoly(Posted 2005) [#2]
I have vsync off... That my seriously hurt me especially if you're making something in 2d. ;-)


Banshee(Posted 2005) [#3]
It's just shoddy not to have at least a frame limiter, it's 1 line of code to put a very simple cap on the framerate, or two lines for a complicated framerate cap... The upshot is that unless people steal your PC in it's current hardware & software configuration they wont be playing it as it is intended to be played.

If your game is on a compilation CD then you're unlikely to get feedback, if I get a compilation CD and 1 game doesnt work I know what I do ...

This slating aside, which wasn't meant as a personal attack but a "what where you thinking!?", "No time" to put a 6 infront of the 0 in flip 0 ...?

Of course a framerate cap is a far from ideal solution and I personally wouldn't use one. I use delta timing and i've no problems with it - if you start your program with a variable for elapsed duration in mind then you never have to worry about constantly changing the values as the game gets more complicated and slower - and it works for other users who play your game too.

I'm not sure what frame tweening is.

The only snag with delta timing is that you cannot multiply or divide a var each frame, but I get around that by doing any multiplies or divides on an interrupt timer et voila - no issues with delta timing...


trb(Posted 2005) [#4]
Frame tweening is the method Mark Sibly uses in the famous "castle demo" included with blitz3d. there's several threads dedicated to discussing dela timing vs. his method, it's been argued to death with the result usually being "personal preference"

I should have probably mentioned I did test my game on several set ups and different versions of windows, and got comparable results (okay, only five systems, I know..not much of a test)the systems ranged from a 1ghz celeron 16mb vram up to 2.5ghz p4 with 64mb vram. the difference in speed is negligible between them.

As for the frame cap, I did put in a way for the user to switch to the alternate "vwait:flip false" so the CPU waits for the vertical blank instead of the vid card..(I picked this up from reading several threads from "jfk" a while back)

So, hypothetically, if you know by either flip or vwait:flip false you can assume you are getting within a range of refresh rates, the only thing delta timing or frame tweening is good for is for the low end systems that can't keep up?


Banshee(Posted 2005) [#5]
You know in all the time i've had B3D i've never thought to look at the samples...


jfk EO-11110(Posted 2005) [#6]
The most pro method is to use the hardware vsync rate. If you don't sync your flip to the hardware rate, you'l have cut off frames. Since the hardware sync rate may be diffrent depending on the settings, you need to use delta timing to make sure the game is running at the same speed on all machines.

Personally I offer an alternative Flip mode in the game Menu. (VWait:Flip 0 vs. Flip 1, but both are using delta timing)


John J.(Posted 2005) [#7]
Frame limiting:
I personally don't like this method because if the user's computer is a little too slow there's nothing the user can do, although it gets the job done in most cases.

Frame tweening:
Once frame tweening is set up, all time equalization is automated. Frame tweening is very accurate because it "simulates" the computer running at a specific rate (70 FPS, 90 FPS, etc), even if it's really running at 30 FPS. The downside of frame tweening is it's a little slower that other methods, and can even almost lock up if it's trying too hard to catch up.

Delta timing:
I personally prefer delta timing. Although it's slightly harder to impliment, it's clean, fast, and simple. I just call an UpdateSpeeds() function every loop, which updates the scale which will be used in the Eq() function, which is used in all movement (such as "MoveEntity cube, Eq(1), 0, 0", instead of "MoveEntity cube 1, 0, 0"). Delta timing combined with vsync works well, but one of the advantages to delta timing is you can disable vsync and see how fast your game really runs :)


puki(Posted 2005) [#8]
"sswifty" used to use Delta-timing - I thought he was some kind of Delta-timing fanboy they way he used it - then he documented a reason why it was no longer the best option for him. I can't remember what the reason was though and if it has already been mentioned here. However, if I come across his anaylsis then I'll post it here.


John J.(Posted 2005) [#9]
Delta timing definitely isn't an "ideal" way to equalize time and does not suit every purpose. I simply prefer it in most cases because it is fast, simple, and effective.


trb(Posted 2005) [#10]
Thanks for all the responses!

So currently the only thing I have limiting my game speed is flip (or vwait:flip 0 if needed) I can see how there is going to be some variance from someone with a 60 mhz refresh rate vs an 85 mhz refresh rate. From my perspective it doesn't seem too huge of a difference, enough to warrant adding in delta timing or frame tweening. I've also made the assumption that 75-85 mhz is the average range of refesh rates, and that if vsync is disabled by the user that I can rely on vsync:flip 0 as a backup. Is any of this incorrect?

I think what I'm getting at is this..If I create a game that runs smoothly on a 500 mhz processor at the monitor refresh rate of 75 mhz, I can expect that a 2.5ghz processor will run the same at 75mhz as well? the vsync is the limiting factor in both cases? (i.e. no jerking or skipping because the game logic is updating at a rate equal to the smooth monitor refresh rate of the system it is on)

Thanks so much for your input on this


Gabriel(Posted 2005) [#11]
So currently the only thing I have limiting my game speed is flip (or vwait:flip 0 if needed) I can see how there is going to be some variance from someone with a 60 mhz refresh rate vs an 85 mhz refresh rate. From my perspective it doesn't seem too huge of a difference, enough to warrant adding in delta timing or frame tweening. I've also made the assumption that 75-85 mhz is the average range of refesh rates, and that if vsync is disabled by the user that I can rely on vsync:flip 0 as a backup. Is any of this incorrect?


Just about all of it :)

Monitor refresh rates go up over 100, so your game could easily be running twice as fast on some machines as others.

Flip True and VWait:Flip False are the same thing. If VSync is disabled, neither will do a thing and the game will be flying along at 2,3,4,5 times as fast as it should.

Also some monitors ( mainly laptop screens ) don't like Flip False and will be unusable.

You seem to be going to great lengths to avoid adding a few simple lines of code, and I'm not quite sure why.


trb(Posted 2005) [#12]
Sybixsus, you got me..I am trying my hardest not to. I just don't like the stuttering and jerking that you get with adding in delta or frame tweening (even with the best implementations there is still a minor amount)I just wish there was an alternative that could give the same silky smooth results as going without.

For flip vs. vwait:flip false, according to the manual on vwait:
"Note that this command is different to the vertical blank waiting mechanism in Flip because Flip will cause the graphics card (as opposed to the CPU) to wait for the next vertical blank. The vertical blank can be disabled on some graphics cards, hence it is quite common to use "VWait : Flip False" to ensure consistent updates on all setups.
This isn't true anymore? It was my thinking the flip 0 wouldn't be a problem because we're relying on the CPU to wait for the blank, then flip immediately with flip 0.

100 mhz refresh rates, however, definitely throw a wrench into my logic..there's got to be a way to take refresh rate into account to set up a global variable in the beginning that affects speed, without having to recalculate and average frame rates over every loop. If I remember correctly, I think jfk talked about this before...I'll have to look more into this. Thanks for pointing this out to me Sybixsus.


Gabriel(Posted 2005) [#13]
For flip vs. vwait:flip false, according to the manual on vwait:
"Note that this command is different to the vertical blank waiting mechanism in Flip because Flip will cause the graphics card (as opposed to the CPU) to wait for the next vertical blank. The vertical blank can be disabled on some graphics cards, hence it is quite common to use "VWait : Flip False" to ensure consistent updates on all setups.
This isn't true anymore? It was my thinking the flip 0 wouldn't be a problem because we're relying on the CPU to wait for the blank, then flip immediately with flip 0.


I've never read the docs on that before, but if there is no vertical blank, I fail to see how Blitz can wait for it. I guess it's easy enough to disable it in your drivers and see if there is any difference. My point about laptop screens still stands either way, some do not like flip false.


JazzieB(Posted 2005) [#14]
Well, this is certainly an interesting discussion. I'm currently experimenting with a timing method for my future projects, as I've always relied on the simple frame limiter method before. Of course, this doesn't work on slower machines, so I'm playing with something like this...

Global logicFPS=1000/200   ; update logic 200 times per second
Global gameTime            ; used to sync with system time

gameTime=MilliSecs()
While Not KeyHit(1)
  While gameTime<=MilliSecs()
    ; update game logic
    gameTime=gameTime+logicFPS
  Wend
  RenderGame()
Wend

Basically, logicFPS is the time interval between each game update. gameTime is the point in time in relation to the system time that the game is in (not sure if that made sense!). Or, when the game state next needs to be updated. The loop then updates the game state as many times as required until it has caught up. It then renders the scene and goes back to updating the game state.

What I have discovered so far is that I need to update the game state a high number of times per second in order to give a smooth display - hence the 200 in the above example. If I use a figure close to the actual refresh rate of the monitor there is visual skipping and catching up visible.

The other problem with the code as it is is that there is a chance it can lock up on slow systems if the whole game state update takes more then the interval required. For example, the above would update the game every 5ms, but if this took 6ms or more the logic would never catch up. I am planning on solving this issue with a slightly more advanced system, although I've only really started messing with timing code today.

I'd be interested to know what people's thoughts are on this method - or is it actually one of those already mentioned and I didn't even know it?!


jfk EO-11110(Posted 2005) [#15]
Quote: "Flip True and VWait:Flip False are the same thing. "

This is not 100% correct. Flip 1 is always synced at 50 HZ where Vwait depends on the current hardware settings, usually 60 Hz by default.

Both methods fail on some systems, so it's a good idea to offer both. I'd also suggest to measure the time that elapses between two vsync commands to determine if the machines vsync works at all. If it is less than say 2 Millisecs, it seems to be disabled. In this case I'd use Flip 1 right away.

; in the program initialisation
vwait
t1=millisecs()
vwait
t2=millisecs()
if(t2-t1)<3 then 
 print "You have disabled hardware Vsync"
 user_flipmode=1 ; or something
endif


Of course, you should mesure the time of Flip 1 too, exactly the same way. If both, vwait and flip true fail, you still can use a cpu-controlled timing, something like:

; in the mainloop
ms=millisecs()
if ms>= nextframe
 nextframe=ms+20 ; = 50 Hz
 flip 0
endif



big10p(Posted 2005) [#16]
Personally, I just use:
fps_timer = CreateTimer(60)

While Not KeyHit(1)
  .
  .
  .

  WaitTimer(fps_timer)
  VWait : Flip False
Wend


This locks the FPS to 60, regardless of the monitor refresh rate.

[edit] Of course, if the FPS doesn't divide exactly into the monitor refresh rate, things may not be quite as smooth.


trb(Posted 2005) [#17]
jfk, I was reading another thread similar to this one where you talked about checking the vsync. also on that thread was a discussion about calculating refresh rate to figure out a constant speed modifier (instead of recalculating delta time each loop)

Reno uses this method in his game:
http://www.blitzbasic.com/Community/posts.php?topic=44650

He offers three game timing methods. 1. user changes monitor refresh rate to 60, game just uses flip for frame limiting 2.delta timing, or 3.program calculates the monitors refresh rate at init. and modifies game speed accordingly.

What about a check in the beginning to check vsync (using jfk's method), check refresh rate (reno's method), then give the user a few options for "Best gameplay experience". (Would it be too much for a game to ask the user to adjust refresh/vsync settings?) I know I keep pushing the delta time/frame tween methods off, it's just such a tease to see your game run so smoothly on your own computer...then have to add in code that takes it away so everyone with fast refresh rates/turning off vsync/etc. can play.


Gabriel(Posted 2005) [#18]
Flip 1 is always synced at 50 HZ where Vwait depends on the current hardware settings, usually 60 Hz by default.


No it does't. If it's supposed to, it's broken and has been for many years. ( Which wouldn't entirely surprise me. )

Flip True syncs at my monitor refresh rate and always has. My old CRT syncs at 85hz in 640x480, 72 in 800x600 and 60 in 1024x768, and my TFT sync at 60 in all of them.


This locks the FPS to 60, regardless of the monitor refresh rate.


Correction. It locks the FPS to 60, providing the computer you're running it on can keep up. If you're running on a PC that can't manage 60 FPS, the game will slow down as the FPS drop, which is not generally a good idea.


it's just such a tease to see your game run so smoothly on your own computer...then have to add in code that takes it away so everyone with fast refresh rates/turning off vsync/etc. can play.


You know, if you're not getting smooth results from delta timing or render tweening, you're either doing it wrong or you're listening to the wrong people. SkidRacer released a demo of his game a couple years back, and it used Render Tweening at 30 ( I think ) FPS. It was incredibly smooth on my old tft, at any resolution/refresh rate. I've used both render tweening and delta timing with very smooth results across the board too. ( Perhaps not *quite* on Skidracer's standards, but as smooth as it was with no game-timing at all )

Game timing really should not be be messing up your smoothness. If it is, I quite understand your reluctance, but you're much better off solving the problem with your timing code than you are asking users to change their vsync or having games running at different speeds.


jfk EO-11110(Posted 2005) [#19]
Quote:
"... calculating refresh rate to figure out a constant speed modifier (instead of recalculating delta time each loop)"

I think this is not a good idea because the number of polies and surfaces to render is not constant. sometimes when you are standing at the end of a map and watch the skybox only your machine will render only a couple of tris and therefor it's gonna be fast. As soon as you turn around, the polycount increases immediately to a 100k and more. The framerate may drop to 30 Hz, 20 Hz, or even less on an older machine. If you don't update delta timing each loop, your character may walk 3 times slower all of a sudden.

Also, the argument of delta timing, the speed factor, may also be used as the time parameter in Updateworld(t#). This will adjust the animation speed of all animated meshes with Delta T in a simple way.

BTW: Flip 1 gives me 0ms on both machines. Both have LCD Displays.


trb(Posted 2005) [#20]
Okay guys, I'm throwing in the towel!

"Game timing really should not be be messing up your smoothness. If it is, I quite understand your reluctance, but you're much better off solving the problem with your timing code than you are asking users to change their vsync or having games running at different speeds."

Agreed..and I will be looking more in depth at delta timing. it looks as though it's my version of delta timing that's causing the issue, not the method itself. thanks to everyone for fielding all my questions and pointing me in the right direction


WolRon(Posted 2005) [#21]
Try using the Delta timing method described on my website and see if it works fine for you.

(I realize now, that I should have a timing comparison example...)

EDIT:
So, I made one:
;Timing comparison example
Graphics 800, 600
box = CreateImage(64, 64)
SetBuffer ImageBuffer(box)
Color 255, 0, 0
Rect 0, 0, 64, 64
SetBuffer BackBuffer()

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;First example; using a simple timer to set the framerate
;Notice that the FPS is set to 47 to intentionally not be
;compatible with the current screen refresh rate

xpos = 0

timer = CreateTimer(47)

While Not KeyHit(1)
	;Move the box
	xpos = xpos + 4
	DrawImage box, xpos, 300
	If xpos > 800 Then xpos = 0

	Text 0, 0, "Without Delta-timing..."
	Text 0, 20, "Press Esc to continue."
	
	;Flip the screen
	WaitTimer(timer)
	Flip
	Cls
Wend

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Second example; using Delta-timing to achieve a smoother movement

Type FrameRate
  Field TargetFPS#
  Field SpeedFactor#
  Field CurrentTicks
  Field FrameDelay
End Type

Global FL.FrameRate = New FrameRate
FL\TargetFPS# = 47
FL\FrameDelay = MilliSecs()

xpos = 0

While Not KeyHit(1)
	;Set Speed Factor
	FL\CurrentTicks = MilliSecs()
	FL\SpeedFactor# = (FL\CurrentTicks - FL\FrameDelay) / (1000.0 / FL\TargetFPS#)
	If FL\SpeedFactor# <= 0 Then FL\SpeedFactor# = 0.00000000001
	FL\FrameDelay = FL\CurrentTicks
	
	;Move the box
	xpos = xpos + 4 * FL\SpeedFactor#
	DrawImage box, xpos, 300
	If xpos > 800 Then xpos = 0
	
	Text 0, 0, "With Delta-timing..."
	Text 0, 20, "Press Esc to end."
	
	;Flip the screen
	Flip
	Cls
Wend
End



Shifty Geezer(Posted 2005) [#22]
Does anyone have tips for Delta timing with physics engines? I think, in the case of ODE, one can calculate a step rating for the simulation advancement, but it doesn't seem clear. I use dWorldQuickStep(0.10) on my Athlon 2500 with VSync on, and dWorldQuickStep(0.15) on a K6 233 with VSync on (lower frame rate but it's useable). I don't know how to determine what step needed based on delta time, especially if the GPU might be a bottleneck in some instances.

My solution to date has been to lock to VSync and not worry if it's slightly faster (75Hz vs 60Hz) on some machines, but if I'm going to implement different Step rates on different machines to keep the simulation at least useable, I may as well try to incorporate proper delta timing.