Jerky Movement Code

BlitzMax Forums/BlitzMax Programming/Jerky Movement Code

Jay Kyburz(Posted 2005) [#1]
I think something is wrong with my game timing and main loop.

I have locked the frame rate to 50 fps (or 20 ms). Basically I measure the time since last frame and wait any unused time until 20ms has passed, then increment the position of objects and render again.

It may be my imagination but the movement seems really jerky and uneven. I know 50 fps is slow these days but there is an unevenness that I would not have expected. I've tried it at 100fps and the problem still exists. I'm using frame deltas and have even logged them. They seem to be working correctly, always exactly 20ms.

I'd appreciate if you guys could take a look and see if you think it looks a bit rough as well. Have you seen this is your projects and how did you fix it?

http://www.jaykyburz.com/files/GameTest.zip


I've read about some c++ guys doing sub pixel rendering. Does Bmax support this? Are the screen x and y passed to DrawImage converted to ints somewhere?


Sledge(Posted 2005) [#2]
If you are locking your game to 50Hz and the lowest rate your monitor supports is, say, 60Hz (like mine) then of course it will look jerky. The highest rate mine will support at some resolutions is 85Hz, so both your examples (60 and 100Hz) would fail to sync correctly for me.

Post another test that attempts 60Hz and I will happily check that out - the one you've got at the time of writing does indeed look a bit jerky on my setup.

EDIT: Also, delta-timing is also bound to introduce jerkyness - if you've got an object that has to move a fixed two pixels right every frame at a resolution of 800*600, that's not going to translate into a fixed pixel distance per frame at either 640*480 (1.6 pixels per frame) or 1024x768 (2.56 pixels per frame). Sub-pixel rendering would help mask this and although Max does pixel-perfect 2D by default (crosses fingers and hopes that's correct) I would be surprised if it wasn't available (I'm waiting for the 3D module and decent audio so can't investigate - perhaps the OpenGL forum here could shed better light on this issue).


Jay Kyburz(Posted 2005) [#3]
oh.. i should add I've disabled vsync

I was just looking at the example here
http://www.blitzbasic.com/Community/posts.php?topic=50249

and if you add a 20 ms delay and disable vsync you get a similar jerkiness. Perhaps not as bad. If you enable vsync it look crap like my game so perhaps I'm not disabling vsync properly.


Strict

'SetGraphicsDriver D3D7Max2DDriver()
Graphics 800,600,32',NOSYNC

Local x = 0

Repeat

	If KeyHit( KEY_ESCAPE ) Then Exit

	x = x + 1
	If x > 800 Then x = 0

	Cls
	DrawRect x, 0, 32, 50
	Flip
	
	Delay (20)

	FlushMem

Forever

End




Jay Kyburz(Posted 2005) [#4]
also, if somebody points me in the direction of the formating stuff for the fourm that would be great. :)


Hotcakes(Posted 2005) [#5]
The problem is this : your screen does not get updated with the graphics the same speed as your program is producing them. The refresh rate of most people's screens is probably going to be 75 or 85 - but let's use an example of 60.

If you program your game to use a set speed of 50 frames a second, what will happen is that every 1 in 5 frames will be doubled, compensating for the extra 10 frames per second. This is what causes the notable jerkiness.

The ultimate solution is to find out what refresh rate the graphics card/drivers/directx/opengl/whatever have chosen to kick into - however this doesn't seem to be possible in directx7, don't know the situation for dx9 or ogl - if you could find out the exact number you can adjust all the timing in your game by that amount... but since you can't, well, there's other ways. You -could- force the refresh rate setting to a number chosen by you - but you have to be extra careful that the gfx card or monitor can handle it - and even if the drivers tell you it can be handled, they could be lieing. This is what BlitzMax tries to rely on. It seems to be the preferred way...

Another option is to run your game at 1000 fps =] That will look smooth on anybody's system (if it can handle the computations) =]


ozak(Posted 2005) [#6]
Why not disable vsync and the use delta timing to make sure it runs the same speed in all cases?


Jay Kyburz(Posted 2005) [#7]
For anybody interested I just decided to run my update at 10ms or 100 fps instead of 50. I spent many hours last night playing with all kinds of systems for stepping time and decided that 50fps is the problem not some inaccuracy in the movement calculations.


Wiering(Posted 2005) [#8]
I was playing around with Jay´s code, running in a window now. If I change the driver to OpenGL, I do get perfectly smooth motion without tearing! (set the frequency to something the same or higher than your actual monitor frequency).

Using the D3D7 driver there is always tearing. Even if I set the frequency to 85 Hz (which is what my monitor does), the tearing keeps staying at the same place for a while.

<code>
Strict
' SetGraphicsDriver D3D7Max2DDriver ()
SetGraphicsDriver GLMax2DDriver ()
Graphics 800, 600, 0, 100
SetClsColor 0, 50, 150
SetColor 255, 240, 210
Local x = 0
Repeat
x = x + 8
If x > 800 Then x = 0
Cls
DrawRect x, 0, 32, 600
Flip
FlushMem
Until KeyHit (KEY_ESCAPE)
End
</code>


Steve Elliott(Posted 2005) [#9]
I get tearing in Wiering's example for both OpenGL and DirectX - only when the refresh rate matches my monitor refresh rate does it disappear.

btw Jay Kyburz, the formatting codes can be selected from the Home Page, FAQ then Website - Forum.