Jump to content
  • Advertisement
Sign in to follow this  
jolyqr

A game timer

This topic is 4501 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
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!