Timing System

Started by
8 comments, last by HellRiZZer 18 years, 8 months ago
First of all I would like to mention that I speak in terms of 2D games, not 3D, yet I'm sure these concepts are very similar in both. Currently the ONLY type of timing system I know how to implement is FPS. Basically I have a loop that will record the current time, execute the game functions, and once a single "frame" has been rendered, it will check the last recorded time to see if 33ms has passed. This offers the ability to limit the loop iterations to 30 frames per second, also known as the FPS timing system. There is another timing system, RTS, Real Timing System. All I know is that this is based on recording the time each iteration takes to execute, and move objects and render specific effects based on this time. This way, no matter how many frames per second you have, objects will always move at the same speed. I am interested in doing things like fading out text. Over the period of, for example, 3 seconds, I want an object on the screen to fade from 100% Opacity to 0% Opacity, basically a fade-out. Many games implement fading and other special features like this, yet I have no idea how to do this. Would anyone be kind enough to show me how this can be done? I would really appreciate it. I believe once I understand how to complete my above scenario, then I will be able to handle any other type of effect I want to do. Also if someone could teach me how to implement an RTS timing system, I would appreciate that as well. I believe RTS is used in every game today, I hardly believe FPS timing is used anymore, yet I wouldn't know for sure. Thanks!
Advertisement
Fading is a rather simple effect. You need a time interval and pressure. Time interval is how much time you want between fading "frames" and pressure is how much to fade in or out each interval. For example, in your case an update function may look somethin like this:
float timeInterval = 50.0f; // in millisecondsint pressure = 5; // how much to add/subtract each intervalvoid update(float elapsedTime) {   static float lastInterval = elapsedTime; // to hold when the last interval was   if (elapsedTime-lastInterval >= timeInterval) {       setOpacity(&obj, getCurrentOpacity(obj) - pressure);// obj would be the obj to change opacity, those functions obviously aren't real// or may be if you define them       lastInterval = elapsedTime; // to set when this interval was   }}

the variables timeInterval and pressure can be used to adjust how fast or slow it fades and how smoothly the fade looks (for example using 500 ms for timeInterval and 5 for pressure would make it choppy).

As for a good timing system, I currently looking for an accurate timer right now too so I can't really help much on that one.
You know the starting value (all white) and you know the destination value (all black). Create a "delta value" to modify the current value.

dA = (endColor.A - startColor.A) / lifeTime;
dR = (endColor.R - startColor.R) / lifeTime;
dG = (endColor.G - startColor.G) / lifeTime;
dB = (endColor.B - startColor.B) / lifeTime;

lifeTime is the time in seconds the effect should transpire for. Let's say you want to fade from white to black in 1 second. The delta values would be -255 ((0 - 255) / 1).

Every frame, add your delta values to your current values multiplied by the frame time (the time in seconds it took your previous frame to render):

a += (float)(dA * frameTime);
r += (float)(dR * frameTime);
g += (float)(dG * frameTime);
b += (float)(dB * frameTime);

If you were running at 2 FPS, your frameTime would 0.5 and your alpha would be -255 * 0.5 = -127.5. This is a quick and easy way to interpolate between values and will always be as smooth as possible (and always accurate).

As far as a timing solution, my timing solution is available here. It's written in C# but should be fairly straight forward if you wish to convert it. Create a new instance of SmartTimer and call Update() every frame. It'll choose between a high precision or a low precision timer, always favouring the high precision timer if available.

At the very least, it'll show you how to calculate DeltaTime (frameTime in the previous example).
the above methods seem over complicated (+ perhaps wrong didnt check) u wann use the following equation

(current_time - start_time) / total_time

eg
(30.0 - 20.0) / 40.0 = 0.25
thus if the effect starts at 20ticks/seconds/years(whatever) + its currently 30ticks its been trunning for 10ticks, divide that by how long u wanna have the effect run for in this case 40ticks + u have your answer
Personally I don't like adding or subtracting a delta value every frame in order to slowly reach the destination value. Floating point imprecisions and can make this an unviable solution as you aren't always guaranteed to have the final color 100% at the end of the duration. Instead, just use simple linear intepolation between the inital and final colors. Do something like this every frame:

color.r = (1.0f - m_fBlendBias) * m_StartColor.r + m_fBlendBias * m_DestColor.r;
color.g = (1.0f - m_fBlendBias) * m_StartColor.g + m_fBlendBias * m_DestColor.g;
color.b = (1.0f - m_fBlendBias) * m_StartColor.b + m_fBlendBias * m_DestColor.b;
color.a = (1.0f - m_fBlendBias) * m_StartColor.a + m_fBlendBias * m_DestColor.a;

Where m_fBlendBias is recalculated every frame as (CurrentTime - StartTime) / Duration. When m_fBlendBias is equal to 1, the blend is complete and the color is now 100% DestColor.
So could someone give me an example of how this would look in a while loop?

For example:

DWORD StartTime = 0;while(true){    StartTime = GetTickCount();    // What goes after this?}


The loop should not be LIMITED to a certain frame rate, rather it should continuously maintain a time that can be submitted to functions that need a time value to determine how much of a change to make for that current frame.

For more examples:

1) One function will move an object from point A to point B at a speed of X. What parameters would this function accept, and how would the movement be calculated?

2) Text should fade out from BLACK to WHITE over a period of X milliseconds. You've already discussed this a lot above, but I would like to see this implemented in the WHILE loop above, if you dont mind.

I don't require TOO much detail, nothing that I can actually compile. Just show me the math I guess.

Thanks guys, I really appreciate it.

As a final question, I would like to ask which timing method you recommend: Limiting the game loop to a certain number of frames per second (say 30, for example), or not limiting the FPS at all, and providing functions a way to perform actions based on a time value.
DWORD ThisTime = 0, LastTime = GetTickCount(), DeltaTime = 0;while(true){    ThisTime = GetTickCount();    DeltaTime = ThisTime - LastTime;    if (DeltaTime > 1000)        DeltaTime = 1000; //This prevents things getting out of control if                          // things freeze up...change 1000 to suit your needs    LastTime = ThisTime;    // Object moving from point A to point B    myobject.Position += (myobject.Velocity * DeltaTime);    // Or for more precision, store the tick count when at point A, then do    // like so:    myobject.Position = PointAPosition + (ThisTime - myobject.PointATime) * myobject.Speed;    // Fade from black to white    mytext.Shade += ((255 / TotalFadeTime) * DeltaTime);    // Where 0 is black, 255 is white :)    // Or, if you need more precise (can't imagine why), store the tick count    // at which the fade started    mytext.Shade = ((ThisTime - mytext.FadeStartTime) / TotalFadeTime) * 255;}


To explain further, everything is given in units/millisecond, so you multiply by DeltaTime (the number of milliseconds since the last frame) to get the number of units to change by in this frame.

Does that help?

Hope so,
Twilight Dragon

P.S. - A good understanding of the equations of constant acceleration is necessary in this area of programming. Pick up a physics textbook and read up.

[Edited by - TDragon on July 18, 2005 4:22:56 PM]
{[JohnE, Chief Architect and Senior Programmer, Twilight Dragon Media{[+++{GCC/MinGW}+++{Code::Blocks IDE}+++{wxWidgets Cross-Platform Native UI Framework}+++
Thank you! That helps a LOT.

Now, since I can't afford a physics book, my next best thing would be a good internet resource that has all of the equations and tutorials concerning physics that I would need.

Anyone know a good website?

Thank you all for your help!
Here's an interesting problem I've faced...

Going from Black to White is easy, you get positive values...

But, going from White to Black isn't so easy because you always have a negative value. You go from 0 to -255 over a period of X seconds.

I need a way to transform this as a steady decline from 255 to 0 over X seconds.

EndColor - StartColor isn't very useful when your start color has larger values than the end color.

I need my 'fade' function to be able to prepare for this situation. How would I change up the algorithm?
try
float fMyInterpColor = ((float)abs(StartColour - EndColour)) / 255.0f;


So, with this code you can have StartColour = 0 and EndColour = 255 OR StartColour = 255 and EndColor = 0, the result is the same.

Cheers.

This topic is closed to new replies.

Advertisement