How do you do your timers?

Discussion in 'Game Development (Technical)' started by Gnatinator, May 9, 2005.

  1. Gnatinator

    Original Member

    Joined:
    Nov 23, 2004
    Messages:
    357
    Likes Received:
    0
    Hey guys.

    I've got a pretty crappy timer system in place for my game atm. Do any of you have any suggestions/code for good high performace timers? (under windows and or unix/osx)

    Thanks :)
     
  2. ggambett

    Moderator Original Member Indie Author

    Joined:
    Jul 26, 2004
    Messages:
    1,982
    Likes Received:
    6
    Heh, try to beat me at crappy timers! I use SDL_GetTicks() with supposedly reports milliseconds, calculate time since last update, and send onUpdate() to various parts of the framework; there, I do this

    Code:
    void PlayMode::onUpdate (float fTime)
    {
    	m_fTimeSinceSomething -= fTime;
    	if (m_fTimeSinceSomething < 0)
    	{
    		m_fTimeSinceSomething = SOMETHING_INTERVAL;
    		doSomething();
    	}
    	
    	...
    }
     
  3. Mike Boeh

    Administrator Original Member

    Joined:
    Jul 26, 2004
    Messages:
    949
    Likes Received:
    0
    Timer.h
    PHP:
    #ifndef TIMER_H
    #define TIMER_H

    #include <windows.h>

    class Timer{
    private:
        
    LARGE_INTEGER    tstartttickstnow;
        
    int Started;
        
    int HighFreq;
    public:
        
    Timer();
        ~
    Timer();
        
    void Start();
        
    int Check(int FracSec);    //Enter the fractions of a second you'd like the result in, e.g. 1000 for ms.
    };

    #endif
    Timer.cpp
    PHP:
    #include <Timer.h>

    Timer::Timer(){
        
    HighFreq QueryPerformanceFrequency(&tticks);
        
    Started FALSE;
    }
    Timer::~Timer(){
    }
    void Timer::Start(){
        if(
    HighFreq){
            
    QueryPerformanceCounter(&tstart);
        }else{
            
    tstart.LowPart timeGetTime();
        }
        
    Started TRUE;
    }
    int Timer::Check(int FracSec){
        if(!
    Started) return 0;
        if(
    HighFreq){
            
    QueryPerformanceCounter(&tnow);
            return (int)(((
    tnow.QuadPart tstart.QuadPart) * FracSec) / tticks.QuadPart);
        }else{
            
    tnow.LowPart timeGetTime();
            if(
    tnow.LowPart tstart.LowPart){    //Oops, millisecond rollover.
                
    return (int)(((tnow.LowPart + (0xffffffff tstart.LowPart)) * FracSec) / 1000);
            }else{
                return (int)(((
    tnow.LowPart tstart.LowPart) * FracSec) / 1000);
            }
        }
    }
     
  4. Pyabo

    Original Member

    Joined:
    Jul 27, 2004
    Messages:
    1,315
    Likes Received:
    0
    So did we ever figure out if QueryPerformanceCounter is still reliable with the new step-down power saving CPUs?

    I seem to recall from another thread that this was an issue...?
     
  5. Larry Hastings

    Original Member

    Joined:
    Jul 27, 2004
    Messages:
    213
    Likes Received:
    0
    We figured out that it is not reliable. On hyper-threaded P4M laptops with SpeedStep, the actual frequency of QPC will jump all over the map. (All the while, QPF will report the same number.) I'm trying to solve this problem in my timing class too, but it's hard to wrap my brain around the eleventy-seven different conditions I have to handle simultaneously. But I'll get there eventually.
     
  6. wazoo

    Original Member

    Joined:
    Jul 27, 2004
    Messages:
    519
    Likes Received:
    0
    timeGetTime and be done with it?

    This could be a question worthy of MS's attention, but for now what's wrong with just sticking with plain ol' timeGetTime()?

    True it may not have the same granularity as the QPF, but for 90% of the projects out there it should be good enough right?

    *shrug*
     
  7. Jim Buck

    Indie Author

    Joined:
    Jul 27, 2004
    Messages:
    1,158
    Likes Received:
    0
    Like I had said in another thread, Quake 2 uses it with no problem. But that game might move so fast that you wouldn't notice the granularity problems. I now when I was making tests with mouse movement, timeGetTime was radically inaccurate.
     
  8. soniCron

    Indie Author

    Joined:
    May 4, 2005
    Messages:
    3,664
    Likes Received:
    0
    If that's the case, and Q2 (obviously) uses mouse input as well, wouldn't that make Q2's mouse input radically inaccurate? Maybe there's a way?
     
  9. Travis Dorschel

    Original Member

    Joined:
    Feb 7, 2005
    Messages:
    84
    Likes Received:
    0
    Hybrid Approach

    Personally I have just used QueryPerformanceCounter in all of my projects and I fall back to a ms resolution (timeGetTime or GetTickCount) approach if it isn't there. I also keep an array of the last X number of frames time steps and average them out for the current time step.

    After the discussion about QPC not being accurate all the time I think I will also use a hybrid approach where the QPC result is tested against the ms resolution and if it is off by more than a few ms the last frames result is used or the ms time is used. Basically I think using multiple timers and comparing the results and averaging out over a number of frames could solve these problems.
     
  10. ggambett

    Moderator Original Member Indie Author

    Joined:
    Jul 26, 2004
    Messages:
    1,982
    Likes Received:
    6
    I second that, do you really need more than milliseconds? Do you even need milliseconds?
     
  11. soniCron

    Indie Author

    Joined:
    May 4, 2005
    Messages:
    3,664
    Likes Received:
    0
    Well, you can run into problems that don't make themselves obviously aparent. For one, with MS accuracy, depending on how you're handling movement in the game, things can get pretty jerky. That can be worked around. However, as someone said on another thread, online play actually gets out of sync, and after a while, they just quit because they're too far out of sync. Same reason why you souldn't cap your framerate at 60FPS (usually), because the granularity doesn't afford you much flexibility if stuff starts getting out of sync. Then again, if it works for ya, stick with it!
     
  12. Jim Buck

    Indie Author

    Joined:
    Jul 27, 2004
    Messages:
    1,158
    Likes Received:
    0
    Since Quake2 is a fast action game, the inaccuracies are probably only a small % of the wide range of mouse movement used in the game. In my own tests, I was plotting graphs of mouse velocity and acceleration while moving the mouse slowly.. I was getting *huge* spikes when using timeGetTime and got baby-smooth graphs when using QPC.

    Though timeGetTime uses milliseconds, and most games wouldn't need more resolution than that, I get the feeling that the milliseconds that timeGetTime *does* give are often divergent from actual milliseconds.
     
  13. Mike Boeh

    Administrator Original Member

    Joined:
    Jul 26, 2004
    Messages:
    949
    Likes Received:
    0
    timeGetTime() can have a granularity as high as 14 ms, meaning that you can't get the precision you need for silky smooth motion....
     
  14. Adrian Lopez

    Original Member

    Joined:
    Sep 7, 2004
    Messages:
    489
    Likes Received:
    0
    A granularity of 14ms would give you 74 clicks per second, which doesn't seem that bad to me.
     
  15. bantamcitygames

    Administrator Original Member Indie Author Greenlit

    Joined:
    Jul 27, 2004
    Messages:
    1,732
    Likes Received:
    78
    Yeah, which is all too obvious when making an arkanoid game.
     
  16. ggambett

    Moderator Original Member Indie Author

    Joined:
    Jul 26, 2004
    Messages:
    1,982
    Likes Received:
    6
    If an object moves at 600 pixels per second, which sounds relatively fast, it will travel 0.84 pixels in 14ms. I'm surprised this isn't smooth enough :confused:
     
  17. Jim Buck

    Indie Author

    Joined:
    Jul 27, 2004
    Messages:
    1,158
    Likes Received:
    0
    Check your math - it would move 8.4 pixels in 14ms. :)
     
  18. soniCron

    Indie Author

    Joined:
    May 4, 2005
    Messages:
    3,664
    Likes Received:
    0
    You have to understand that timeGetTime() isn't very accurate. It's not always exactly 1ms. Because of that, things that are traveling like a ball in an Arkanoid clone can get jerky. 8.4 pixels in 14ms may seem smooth, but it may actually be 8.4px in 14ms, then 8.4px in 16ms, then 8.4px in 8ms, then 8.4px in 13ms. You get the idea. That doesn't look as smooth as it could. But it IS mostly functional.
     
  19. Adrian Lopez

    Original Member

    Joined:
    Sep 7, 2004
    Messages:
    489
    Likes Received:
    0
    I think soniCron makes a good point, as smoothness has nothing to do with how many pixels your sprite moves every second. After all, if your screen has a refresh rate of 70 Hz (70 frames per second, like clockwork), a speed of 600 pixels per second means you'll see it move about 8.5 pixels every frame. With a refresh rate of 85 Hz, you'll see it move about 7.05 pixels every frame. Even with a refresh rate of 120 Hz, it would move 5 pixels per frame.

    Smooth animation is achieved if your sprites, while traveling at a particular speed, move the same distance every single frame.
     
    #19 Adrian Lopez, May 11, 2005
    Last edited: May 11, 2005
  20. Adrian Lopez

    Original Member

    Joined:
    Sep 7, 2004
    Messages:
    489
    Likes Received:
    0
    Regarding problems with SpeedStep, look at what I found on Intel's website.

    Edit: Spoke too soon. I can't find the code for this etimer the paper discusses.
     
    #20 Adrian Lopez, May 11, 2005
    Last edited: May 11, 2005

Share This Page

  • About Indie Gamer

    When the original Dexterity Forums closed in 2004, Indie Gamer was born and a diverse community has grown out of a passion for creating great games. Here you will find over 10 years of in-depth discussion on game design, the business of game development, and marketing/sales. Indie Gamer also provides a friendly place to meet up with other Developers, Artists, Composers and Writers.
  • Buy us a beer!

    Indie Gamer is delicately held together by a single poor bastard who thankfully gets help from various community volunteers. If you frequent this site or have found value in something you've learned here, help keep the site running by donating a few dollars (for beer of course)!

    Sure, I'll Buy You a Beer