Sign in to follow this  

2D GDI and timing question

This topic is 4818 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Rather than do what I usually do, research the heck out of a subject until I get headaches then bring it here, I will start here first :) In pseudocode even if you want, what would be a good game loop timing arrangement? I have a 64x64 object moving across the screen at 4 pixels or increments, per flip (basic bitblt from backbuffer to screen). When I have my timer going (it's a GetTickCount type) and the object is moving on my P4 and slower test puter at that speed, the object tends to jerk - not be so smooth. When I disable the timer, it moves much faster across the screen and doesn't jerk at all. When I say jerk, I mean for about 3/4 of 64 pixels it moves smooth then jumps to the next 64 pixels. Kind of like that only more fluid. I was thinking the timing is slowing it up, along with the message queue.. not sure. Here is my pseudocode for what I have now, and any theory introduced which will help it would be greatly appreciated.
  while !Quit {
       PeekMessage,PM_REMOVE
          if msg.message == WM_QUIT
             Quit=TRUE
          endif
        TranslateMessage,...
        DispatchMessage,...
        
        maingameloop()
        starttick=GetTickCount()
        while endtick-starttick <= GAME_SPEED
            endtick=GetTickCount();
        wend
        BitBlt backbuffer to main screen
     WEND
  ..
  cleanup and gohome here
.
        

Share this post


Link to post
Share on other sites
If you're using frame based movement (4 pixels per frame, etcetera), then it is vitally important that each frame is precisely the length you want it to be. The jerkiness is often a result of the timing mechanism being inaccurate, not inefficient. And GetTickCount() doesn't have a phenomenal accuracy. You can get better accuracy by using things like QueryPerformanceCounter() or timeGetTime() (after a call to timeBeginPeriod(1)). However, those are somewhat dependent on the underlying hardware anyway, and even then can have problems with accuracy, only in different ways. From my experience and reading, it seems that there is not 100% reliable method to getting accurate frame timing, other than actually getting refresh signals from the video adapter itself. But GetTickCount() is often the worst.

Oh, and are you using just straight GDI stuff? Or are you using DirectDraw or some other library? Because I know DirectDraw has a WaitForVerticalBlank() function that will let you synchronize your code to the refresh rate of the video adapter. I depend on a similar method (in Direct3D, not DirectDraw) to manage a rock-solid 60 FPS for a product of mine at work. (Jerky movement of any sort, major or minor, is 100% unacceptable for the product.)

Share this post


Link to post
Share on other sites
You are only processing one message per game loop. That won't work. You need to call PeekMessage until the queue is empty and then do the game loop:

while !Quit {
while PeekMessage,PM_REMOVE
if msg.message == WM_QUIT
Quit=TRUE
endif
TranslateMessage,...
DispatchMessage,...
wend
if !Quit
maingameloop()
starttick=GetTickCount()
while endtick-starttick <= GAME_SPEED
endtick=GetTickCount();
wend
BitBlt backbuffer to main screen
endif
wend

Share this post


Link to post
Share on other sites
I think what you may be describing is something called "shearing." Shearing happens when the buffer is refreshed more quickly than the screen is refreshed. When you fill the buffer so quickly, the contents get flipped when only half of the monitor's screen is drawn, so part of the image is from the old frame, while part is from the new frame. Depending on your refresh rate and fps there may be several shears. The formula for potential number of shears is (fps/monitor refresh) - 1. If your fps is 120, and refresh is 60hz, you will see 1 shear, on average, per frame. If you're app is in a window, the shear may lie outside the window and be un-noticable. Also, the shear may move up and down the screen because the fps is not likely an exact multiple of the refresh.

I've been working to minimize this issue myself, because I have been working on a software graphics library which is drawing to a gdi bitmap, then blitting the bitmap to screen in one pass. Unfortunately in my research of the problem, I have found that the vertical redrace is not exposed to GDI at all, but to get shear-free graphics you must flip only during the vertical retrace (which is the short period of time when the raster is returning to the top of the screen and not drawing anything.) Detecting the retrace makes sure that there is only one "active" frame during the whole time the screen is being drawn to the monitor.

Alas, there is no way to detect the retrace in gdi or directly from windows. The closest I've come to fixing the problem involves a "double-buffered page-flipping" mechanism. There is still one shear, on average, per frame Though. It just doesn't increase with increasing fps.

If it really is shearing as I believe, I appologize for just ruining your day ;-)

Share this post


Link to post
Share on other sites

This topic is 4818 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this