Sign in to follow this  

Timing questions

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

Ive been reading a lot of articles on timing in games and I am still confused. This is how much I have gathered by myself. 1. You need a framestart variable to basically set the program to 0. Since the internal clock starts as soon as the computer does. So when you run your program the internal clock will return something like 1hour etc. in milliseconds because 1 hour has passed since it was active. and I thought I had more but after that I keep getting confused. Also I was wondering what is the difference between frame time and Fps?

Share this post


Link to post
Share on other sites
Quote:
Original post by Shadowwoelf
1. You need a framestart variable to basically set the program to 0. Since the internal clock starts as soon as the computer does.
If you want to measure time relative to something (such as the start of a frame, or the start of the program itself), then yes, this is important.
Store the time value (e.g. in a variable called framestart) when the program/frame/whatever starts.
framestart = timeGetTime();
Then when you need to get the current time later in your program, you can subtract framestart from it, which will give you the elapsed, or relative time since that event:
elapsedTimeSinceFrameStart = timeGetTime() - framestart;
Quote:
Also I was wondering what is the difference between frame time and Fps?

frame time is the length of time elapsed since the last frame. FPS is how many frames can fit into 1 second.
Basically, FPS = 1/frame_time

So if your frame time is ~0.03s then your FPS is ~33

Share this post


Link to post
Share on other sites
The time returned (and in what units the time is expressed) will depend on the language feature or API you use to query the time. It could be the amount of time that's passed since some date in the past, since the computer was booted up, since the application was launched, or since a 'timer' object was created.

What to do with that data is up to you. A typical approach is as follows (pseudocode):
int lastMS = GetMilliseconds();

while (!quit) {
int currentMS = GetMilliseconds();
int elapsedMS = currentMS - lastMS;
lastMS = currentMS;

// ...
}
You would then use 'elapsedMS' as the timestep to drive your simulation.

There are many other ways to go about it, of course. If you need more info though, you may have to ask a more specific question.

Share this post


Link to post
Share on other sites
FPS is the amount of frames that occur in a second(or the average frames per second, over something like the last 10 seconds).
'frame time' how you're using it here, is the amount of time 1 frame is, in milla-seconds.

So: FPS = (frameTime / 1000)


The reasoning for time-based movement/animation/etc in games is due to lag. If you merely limit your games to, say, 50 frames per second, and move the player 10 pixels per frame, if the computer slows down, you might have less than 50 frames for a while, making the entire game move very slowly and the player's actions be delayed as well. This will result in players getting frustrated with your game, if it occurs frequently, or if the slow-down causes their death.

With time-based movement in your games, instead of moving 10 pixels per frame, for 50 frames, you instead move 10 pixels per every '50/1000' millaseconds. If your game suddenly drops to 25 fps, each frame will move the player twice as fast, and to the person playing, his character will be going the same speed regardless of whether he's getting 20 fps, or 50, or 200.

You can implement time-based movement something like this:

//Game startup:
unsigned long int currentTime = GetTimeInMillaSeconds(); //You'll have to replace 'GetTimeInMillaSeconds()' with whatever your API offers.


unsigned long int deltaTime; //This can be renamed 'frameTime' if it helps any.

int playerX, playerY; //Player's location.
int playerTime = 0; //Used to 'store up' time that passes, to use to move the player.

const int playerSpeed = 100; //Player moves 100 pixels per second.

//Main game loop:
while(1)
{
//Update the deltaTime at the beginning of your frame, to be equal to the amount of millaseconds that has taken place since the beginning of the last frame.
deltaTime = GetTimeInMillaSeconds() - currentTime;
currentTime = GetTimeInMillaSeconds();

...

//Movement code:


//playerTime keeps any leftover time it doesn't use for the next frame.
playerTime += deltaTime;

//Move the player an amount of pixels based off his movement speed and the amount of time past.
if(playerTime > (playerSpeed/1000))
{
int amountToMove = playerTime / (playerSpeed/1000);
playerTime = playerTime % (playerSpeed/1000);

//Move the player 1 pixel for every 10 millaseconds that has passed.
if(PLAYER_IS_MOVING_DOWN)
playerY += amountToMove;
}

...

}



I hope my pseudo-code didn't over complicate the matter. [laugh] It's actually pretty simple, and this coming from a person who is bad at math.

Read this: Laxyfoo's SDL tutorials - Lesson 32. It uses the SDL API, but the concept can easily be applied to any API, and any language.

Obviously, it can be applied to 3D games as well. And not just movement, but animation, player attacks, physics of falling objects(or any physics), and pretty much anything that relies else on the passage of time.

Share this post


Link to post
Share on other sites
Well I guess my question is how do I know how much to add to my current time to find out when to update

This is as far as I got


framestart = timeGetTime();
lastframe=framestart
While(!done){
Gameupdate();
Render();
While(timeGetTime()<lastframe+[not sure what to put in here]){}
lastframe=timeGetTime;
}

I want to limit it to around 30fps (2d rpg)

edit: sorry Servant of the Lord you posted while I was replying.
I don't understand what player time has to do in your example. And shouldn't the currentTime be called after you have finished drawing everything?

[Edited by - Shadowwoelf on May 27, 2008 12:29:44 AM]

Share this post


Link to post
Share on other sites
You can, of course, create an empty loop, but that would be inefficient and ugly (correct me if wrong). Instead use sleep().


const DWORD DesiredFrameLength = 33; // ~30 FPS
DWORD StartTime = timeGetTime();
DWORD LastTime = StartTime;

while(!Done)
{
DWORD ElapsedTime = timeGetTime()- LastTime;

if(ElapsedTime < DesiredFrameLength)
{
sleep(DesiredFrameLength - ElapsedTime);
ElapsedTime = DesiredFrameLength;
}

LastTime = timeGetTime();

GameUpdate(ElapsedTime );
Render(ElapsedTime );
}


Share this post


Link to post
Share on other sites
Koobazaur why do you have
ElapsedTime = DesiredFrameLength;

in that if statement when elapsed time will be overwritten when the loop restarts?

And shouldn't the DesiredFrameLength be in the thousands range? because if you first run the program Sleep will only be called every 33 seconds?

Share this post


Link to post
Share on other sites
That's because the GameUpdate and Render that rely on elapsed time (at least in my implementation) are called before next loop iteration, so your calculation for elapsed time would be off if you didn't re-set elapsed time to desired. If you follow the logic you'll see that these functions will always received the elapsed time equal to desired or greater, whereas if we didn't have that statement in if, occasionally they would get elapsed time smaller than desired followed by one greater than desired. In the end the difference wouldn't be too noticable, but this keeps the elapsed time values passed into update more unform instead of oscilating between big and small.

Also, all times are in miliseconds, not seconds. Sleep will be called whenever your elapsed time is smaller than desired time (less than 33 miliseconds), which is impossible to predict when, as it depends on how long your update and render functions take. May be every single loop, may be never.

Share this post


Link to post
Share on other sites
... no, DWORD is Microsoft type that stands for "double word" which is a 32 bit unsigned integer. There is no data type specicially for miliseconds as miliseconds are just numbers. It's entirely up to you and the rest of your code how you interpret these numbers.

timeGetTime() returns a DWORD value that represents the amount of miliseconds that passed since Windows booted.

read more at: http://msdn.microsoft.com/en-us/library/ms713418.aspx

also, in windows programming (which timeGetTime() is a part of), Microsoft defined custom data types for all the base types (CHAR for char, INT for int, DWORD for a 32 bit unsigned int etc.). This is done because C++ does not guarantee data type sizes, only their minimum (that is, a char is guaranteed to be at least 8 bits, but it may be more on different platforms! ). Hence, custom types are defined to ensure that they are always the same size, regardless of the platform (example: int may be 32bits on one system, but 64 on another, whereas INT will always be 32)

here's a list of all win32 data types: http://msdn.microsoft.com/en-us/library/aa383751(VS.85).aspx


And as for elapsed time - it's just that, elapsed time. It can be used to make your program run at a given speed regardless of frame rate. You can use it to move your untis (unit.position += unit.speed * elapsed_time), you can use it to animate spries (sprite.frame += frames_per_milisecond * elapsed_time), you get the idea.

A lot of people make FPS bound games and measure the game time via FPS (i.e. move a unit 3 pixels every frame or change animation to next frame ever 3 frames). However, I greatily advise to use actual time itself. It's more accurate, it's more flexible, and your in-game time will not slow down if your FPS goes down. That, and you can still put a limit on your FPS using time, so you aren't losing any functionality.

Share this post


Link to post
Share on other sites
But in this section of the code

const DWORD DesiredFrameLength = 33; // ~30 FPS

You make it 33 which makes it an integer?

And by using 'actual time' your referring to moving units per elapsed time right? Because that way if fps goes up or down the user won't notice it

Edit: Also why would my render function need ElapsedTime ? Doesn't it just draw what it is given?

Share this post


Link to post
Share on other sites
Quote:

But in this section of the code

const DWORD DesiredFrameLength = 33; // ~30 FPS

You make it 33 which makes it an integer?


The 33 doesn't make DesiredFrameLength an integer; it already is (most likely) an integer.

When you declare a variable of a given type, it is that type. Period. You cannot change it. If you have an int var, it will be an int, always. You can assing 12 to it, it will be an int. You can assing 13.8, it will be an int (13). You can assing 'c' to it, it will still be an int (in this case, 99). When you assign 33 to a DWORD, it still is a DWORD (which is an alias for a special kind of an integer).

You see, when you assign a variable of one type to another, it gets "cast" to fit the expected type. Let's take this as an example:

int MyInt = 'c';

You are assigning the character 'c' to an integer. That doesn't make the integer MyInt become a character; instead, it makes the chracter become an integer. How?

Different data types have different ways of "casting" to each other (and you can even define how to cast your own custom made classes and structures into different types!) For something simple like a float (say 13.8), casting gets rid of the decimal (note: it doesn't round it) to make it an integer. How does it work for a character?

Simple - character is actually a number. A number between 0-255, where each of one is associated with a different character. This is the infamous ASCII table:

http://www.asciitable.com/

Lowercase 'c' is associated with 99. Thus, when you do int MyInt = 'c' it is converted to the code representing the character - 99. The inverse is also true, definint

char MyChar = 99;

will make MyChar equal to 'c'.

Keep in mind that only some, logical casts are pre-defined. For instance, it doesn't make sense to convert a string to an integer like so:

std::string MyString("Hello World!");
int MyInt = MyString; //compiler error: error C2440: 'initializing' : cannot convert from 'std::string' to 'int'

As I said, you can define your own casts for your own classes to tell the compiler how to cast it into other types. Seeing as you are confused about variable types I'm guessing you haven't gotten into classes yet, so I won't go into that here.

Going back to the original example:

const DWORD DesiredFrameLength = 33; // ~30 FPS

This would convert the integer 33 into a DWORD. Since DWORD is also an integer, this is a perfectly acceptible cast. DWORD is nothing more than an "alias" for a 32 bit unsigned integer (most like simply an "unsigned int"), it's not a class. And if it is, then whoever defined it better provide methods of the DWORD class to allow it to cast to integers and take on an integer value.

On a more low-level note, all variables are, in fact, numbers. Yup, they're just blocks of memory, and what is memory? a series of 0s and 1s - numbers. Giving variables a type (int, char, string) merely tells your program how it should interpret this number. An unsigned int tells it "ok, treat this number as if it was a number that cannot be negative." An int tells it "ok, so treat this number as either a positive or negative one; the 1 or 0 at a certain position will tell you if it's positive or negative, and the rest will give you the value of the number." A char tells it "treat this number as if it was a character, so if someone want to display it to the screen use a character from the ASCII table associated with this number." Even when you build your own complex classes that are made of integers, characters and other stuff, they're still just a series of 1s and 0s, where different parts of this 1010101etc sequence corresponds to different bits of information.


It seems you haven't quite grasped variables yet, so read up about them here http://www.cplusplus.com/doc/tutorial/variables.html

Quote:

Edit: Also why would my render function need ElapsedTime ? Doesn't it just draw what it is given?


I don't know! It depends on what your render function does. It may apply some cool time-dependant effects if you want. It may not do anything at all. As Captain Planet said: "The Power is Yours!"

Share this post


Link to post
Share on other sites

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