• Advertisement
Sign in to follow this  

A game timer

This topic is 4330 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

I heard that using a timer in a video game makes the game more professional and allows the game to be played in a lot of computers (slow and fast computer). So I have integrated a timer similiar to the one which is in the following link http://www.gamedev.net/reference/articles/article753.asp Now all the objects of my game that move use the game timer factor, even the player movements. naively I thought it would make my game better, but I have noticed that sometime, the game runs in a weard way. basically the rendering becomes jurky, it's like the timer factor becomes too big, so when I move the player character, its movements units becomes too big, so it disapears completely from the game world. it's the same for my NPCs... if someone understand something, let me know cheers !!

Share this post


Link to post
Share on other sites
Advertisement
I am not real sure of the problem (besides, I was just about to get horizontal...) but just a guess:


When you time your loop, your timer should collect a delta T of the "Real time" that has passed in clicks/quanta/etc... This should not be cummulative, what you are sort of trying to measure is the amount of time that has passed since you last rendered a frame. So for example:

Target = 20 FPS
Clicks per second = 1000

Therefore every loop I should only have about 50 clicks go by.

So imagine you have a stopwatch, you start it and meanwhile a guy named "render" starts running around the track. You keep the watch going, but every time "render" passes you, you make a note of the 'clicks' that have passed. You want to take the difference between the last lap and the current lap - or lap/unit_time.


So, your timer factor should never become 'too big' in regards to your objects and their movements (unless you have some other things that unpredictably take a LARGE amount of time - in which case you need to do profiling).

So, First, if you implemented the timer differently then described then go back and make sure you only pass the diff. If thats the case, or there are still problems, try logging out the loop time for 10-15 seconds (or whatever length of time you need to see the event happen). See if you can find any odd increases in your 'loop time'. You could also do some logging with that to sort of profile what causes your odd game loop cycles.

If that isnt it, then I/we need more data or code snips to help you determine the problem.


Hope that helps...

#dth-0

Share this post


Link to post
Share on other sites
It is hard to say anything without having a look to your code. Are you correctly using the time factor? Did you correctly implemented it? There are plenty of different reason why it may be wrong.

Can you show us at least your timee code and a typical use of your code?

Thanks :)

Share this post


Link to post
Share on other sites
i have build a class, here is the class declaration:


#pragma once
#include <iostream.h>
#include <windows.h>

namespace myTimer
{
class Timer
{
public:
__int64 startclock;
double rate_inv;
float frametime;
float framestart;
float frameend; // the vars really needed
float first;
float fps;
float frametimes;
private:
void wait(void);
void update(void);
BOOL initftime(void);
double ftime(void);
public:
Timer(void);
void standalone(void);

public:
~Timer(void);
};
}

Share this post


Link to post
Share on other sites
here are the class methods:

#include "Timer.h"

namespace myTimer
{
Timer::Timer(void)
{
float frametime,framestart,frameend; // the vars really needed
float first,fps,frametimes=0;
}

Timer::~Timer(void)
{
}

void Timer::update()
{
frametime=frameend-framestart; // find differnce to get the frametime
framestart=frameend; // make the first time be the next time
frametimes+=frametime;
// the inverse of frame time is the frame rate
fps=1.0/frametime;
}

void Timer::standalone(void)
{
initftime();
wait();
update();
}

void Timer::wait(void)
{
// get the time till its not equal to start frame time, it should,
// never loop at the rate of this timer, but if it does then
// it will cap to the frame rate to the rate of this timer which
// is 1193180 hz
do
{
frameend=ftime(); // get end of frame time
}
while(frameend==framestart);
}

BOOL Timer::initftime(void)
{
__int64 rate;

// we need the accuracy
if(!QueryPerformanceFrequency((LARGE_INTEGER*)&rate))
{
return FALSE; // win errors
}

// usually the rate will be 1193180
if(!rate)
{
return FALSE;
}

rate_inv=1.0/(double)rate;

if(!QueryPerformanceCounter((LARGE_INTEGER*)&startclock))
{
return FALSE; // win errors
}
framestart=ftime(); // get the first time
first=framestart;
return TRUE; // there is a clock
}

// you would have to start up with initftime() at the beginning
// of the game. And check for errors

double Timer::ftime(void)
{
// by dividing by its rate you get accurate seconds
__int64 endclock;
QueryPerformanceCounter((LARGE_INTEGER*)&endclock);
return (double)(endclock-startclock)*rate_inv;
// note: I recommend that you multiply but the inverse of a constant.
// (speed reasons)
}
}

Share this post


Link to post
Share on other sites
here is an example of the using of that class:

myTimer::Timer timer1;

int DrawGLScene(GLvoid) // Here's Where We Do All The Drawing
{
// timer of the game
timer1.standalone();


// game stuffs

return TRUE;
}


This is the loop function of the game, basically, we just have to call the standalone() method and it does everything for us.

Share this post


Link to post
Share on other sites
void Player::MoveRight(float frametime)
{
SetRotate(-90,0.0f,0.0f,1.0f);
if(isliving==false)
{
weapon.SetScale(0.1f,0.01f,0.01f);
}
if(PositionX>=limX)
{
PositionX =PositionX;
}
else
{
PositionX +=7000.0f*frametime;
}
}

here is an example of the using of the frametime in the player movements

Share this post


Link to post
Share on other sites
Original post by jolyqr
here are the class methods:


#include "Timer.h"

namespace myTimer
{
Timer::Timer(void)
{
float frametime,framestart,frameend; // the vars really needed
float first,fps,frametimes=0;
}

Timer::~Timer(void)
{
}

void Timer::update()
{
frametime=frameend-framestart; // find differnce to get the frametime
framestart=frameend; // make the first time be the next time
frametimes+=frametime;
// the inverse of frame time is the frame rate
fps=1.0/frametime;
}

void Timer::standalone(void)
{
initftime();
wait();
update();
}

void Timer::wait(void)
{
// get the time till its not equal to start frame time, it should,
// never loop at the rate of this timer, but if it does then
// it will cap to the frame rate to the rate of this timer which
// is 1193180 hz
do
{
frameend=ftime(); // get end of frame time
}
while(frameend==framestart);
}

BOOL Timer::initftime(void)
{
__int64 rate;

// we need the accuracy
if(!QueryPerformanceFrequency((LARGE_INTEGER*)&rate))
{
return FALSE; // win errors
}

// usually the rate will be 1193180
if(!rate)
{
return FALSE;
}

rate_inv=1.0/(double)rate;

if(!QueryPerformanceCounter((LARGE_INTEGER*)&startclock))
{
return FALSE; // win errors
}
framestart=ftime(); // get the first time
first=framestart;
return TRUE; // there is a clock
}

// you would have to start up with initftime() at the beginning
// of the game. And check for errors

double Timer::ftime(void)
{
// by dividing by its rate you get accurate seconds
__int64 endclock;
QueryPerformanceCounter((LARGE_INTEGER*)&endclock);
return (double)(endclock-startclock)*rate_inv;
// note: I recommend that you multiply but the inverse of a constant.
// (speed reasons)
}
}

[/quote]

You should use [source lang="cpp"][/source] around your code.



There is nothing really wrong with your class - except the fact that everything is public. I guess your problem comes from how you use it. Can you give us an example (taken directly from your code, with some intelligent strip off - because we don't really want to have to handle large chunk of code (you know, we are lazy [smile])).



BTW, while this has probably nothing to do with your problem (unless your are using your wait() function everywhere)


do
{
frameend=ftime(); // get end of frame time
}
while(frameend==framestart);


This can't work. You can't test the equality of 2 floating point values, due to the restiction of the floating point format. you have to test fabsf(frameend-framestart) < epsilon, with epsilon being a small value.


double Timer::ftime(void)
{
// by dividing by its rate you get accurate seconds
__int64 endclock;
QueryPerformanceCounter((LARGE_INTEGER*)&endclock);
return (double)(endclock-startclock)*rate_inv;

// note: I recommend that you multiply but the inverse of a constant.
// (speed reasons)

}

Kidding, right? You might call this function maybe 1000 times per second max, so the div can't kill you. The sub on 64 bit quantities might take more time than the div itself :)

Regards,

Share this post


Link to post
Share on other sites
Quote:
Original post by jolyqr
here is an example of the using of that class:

myTimer::Timer timer1;

int DrawGLScene(GLvoid) // Here's Where We Do All The Drawing
{
// timer of the game
timer1.standalone();

// game stuffs
return TRUE;
}


This is the loop function of the game, basically, we just have to call the standalone() method and it does everything for us.


??? What does it mean?

The standalone() method just init the whole stuff and wait for something.

Oh. I misread wait(). This is a nonsense function thath does nonsense stuff (hence I didn't understood its usage and gave you false indications).

Your timer is not supposed to work this way. If you use it this way, you have a waiter, not a timer. You are supposed to init it at the beginning of your application, and then adjust how you should update your game content depending on how much time has passed since your last update:

// a new Timer method
float Timer::frameDuration()
{
float newEnd = ftime();
float oldBegin = mBegin;
mBegin = newEnd;
return newEnd - oldBegin;
}

// your application
Application::Application()
{
mTimer.initftime();
}

Application::update()
{
// last frame time
float lastFrameDuration = mTimer.frameDuration();

// this sprite has its own velocity:
sprite.translate(sprite.getVelocity() * lastFrameDuration);
}


I believe you should carefully read again the article you used to implement your timer, because it seems that you don't fully understand its goal and the implementation.

If you need help, we are still here [smile]

Regards,

Share this post


Link to post
Share on other sites
Quote:
Original post by Emmanuel Deloget
Quote:
Original post by jolyqr
here is an example of the using of that class:

myTimer::Timer timer1;

int DrawGLScene(GLvoid) // Here's Where We Do All The Drawing
{
// timer of the game
timer1.standalone();

// game stuffs
return TRUE;
}


This is the loop function of the game, basically, we just have to call the standalone() method and it does everything for us.


??? What does it mean?

The standalone() method just init the whole stuff and wait for something.

Oh. I misread wait(). This is a nonsense function thath does nonsense stuff (hence I didn't understood its usage and gave you false indications).

Your timer is not supposed to work this way. If you use it this way, you have a waiter, not a timer. You are supposed to init it at the beginning of your application, and then adjust how you should update your game content depending on how much time has passed since your last update:

*** Source Snippet Removed ***

I believe you should carefully read again the article you used to implement your timer, because it seems that you don't fully understand its goal and the implementation.

If you need help, we are still here [smile]

Regards,


please let me know if i'm mistaking. basically, i have understand that if i don't use any timer in my games, these games could be too fast in fast computer and slow in other computers.

using a factor depending on the processor frequency makes the game characters moving in the same way regardless of the computer processor...

Share this post


Link to post
Share on other sites
Yup (awake again) - re-read my post on what you are trying to do. In direct terms:

Your game has a "main loop" and within it there is some function that renders all of your art to the screen. This function should loop endlessly until you exit the program.

The beginning of this loop should query the timer and determine how much time has passed since the last time it was called. You get this by subtracting clicks this loop minus clicks last loop.

You should already have done a calculation that determines how many clicks correspond to actual time in the real world (this would be where everything moves at the same speed, regardless of how fast your computer is..).

Then, you determine if enough clicks have gone by before you go and render. If they have not, then you just return. Psuedo-code:



function render_loop()
{
static last_loop_time = timer.getTime(); // static init only happens once
this_loop_time = timer.getTime();

time_past = this_loop_time - last_loop_time;

if( time_past < desired_timing )
return; // loop to quick, dont render yet.

render_stuff( time_past ); // enough time - render objs.
}


This is the basic idea. Once you get it going, you can use the 'slack time' to do things like AI. Also, you can make this more granular by letting each object decide if enough time has past. This allows you to have each object determine how fast it is relative to other objects in the game - but for now just get the loop working.


HTH -


#dth-0


return;

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement