deltaTime issues

Started by
8 comments, last by BeerNutts 12 years, 5 months ago
First of all, I should note that I am developing this engine for the android OS, so memory, CPU speed, and GPU speed are all limited. I am also using Java, however on most relatively newer android devices--provided they are running at least android 2.2--Java is JIT compiled rather than interpreted. i am also making use of the JNI and native code whenever I see fit.

At any rate, I am having some issues implementing a deltaTime variable.
I have this class"


public class Time
{
public static long timeFrameStarted = 0; // system time at start of frame
public static long timeOfStart; // system time of the start of the scene
public static float deltaTime = 0; //time it took to complete last frame
public static long frameCount = 0; // Number of rendered frames
}


and my update function called each from looks like so:


public void onDrawFrame(GL10 gl)
{
Time.timeFrameStarted = System.currentTimeMillis();
++Time.frameCount;
Log.e("IMPACT", "" + Time.deltaTime);
// TODO Auto-generated method stub
go.transform.position.x += 100 * Time.deltaTime;
go.update();
Time.deltaTime = (float)((System.currentTimeMillis() - Time.timeFrameStarted)/1000.f);
}


go is my GameObject. Everything else should be self explanatory.

At any rate, this code does work, however as the game object is moving across the screen, it will move smoothly, then jerk forward, move smoothly again, then jerk forward again, and so on.

I am not sure if it has something to do with my implementation of deltaTime or if I simply need to optimize my openGL code inside of my draw methods.

Here is a video of the issue in case it helps:
Co-founder/Lead Programmer
Bonafide Software, L.L.C.
Fairmont, WV 26554 US
Advertisement
Well, after thinking about it some more, I realized that this should be expected from the code. I am moving my object by a different value every frame.
So I suppose the correct question should be, what should I do instead?

I am aiming for frame-rate independence, by the way.
Co-founder/Lead Programmer
Bonafide Software, L.L.C.
Fairmont, WV 26554 US

Well, after thinking about it some more, I realized that this should be expected from the code. I am moving my object by a different value every frame.
So I suppose the correct question should be, what should I do instead?

I am aiming for frame-rate independence, by the way.


You're scaling your movement by how much time the last [font="CourierNew, monospace"]onDrawFrame[/font][font="Arial"] call [/font][font="Arial"]took. I assume you want to scale by how much time has elapsed since the last movement?[/font]
[font="Arial"] [/font]
[font="Arial"]Also experiment with the resolution of [/font][color=#1C2837][size=2][color=#660066][font=CourierNew, monospace]System[/font][color=#666600][font=CourierNew, monospace].[/font][color=#000000][font=CourierNew, monospace]currentTimeMillis[/font][color=#666600][font="CourierNew, monospace"]()[/font][font="Arial"] on the android. If it's low enough, you'll get wonky results.[/font]

[quote name='jonbonazza' timestamp='1319077850' post='4874533']
Well, after thinking about it some more, I realized that this should be expected from the code. I am moving my object by a different value every frame.
So I suppose the correct question should be, what should I do instead?

I am aiming for frame-rate independence, by the way.


You're scaling your movement by how much time the last [font="CourierNew, monospace"]onDrawFrame[/font][font="Arial"] call [/font][font="Arial"]took. I assume you want to scale by how much time has elapsed since the last movement?[/font]

[font="Arial"]Also experiment with the resolution of [/font][color="#1C2837"][color="#660066"][font="CourierNew, monospace"]System[/font][color="#666600"][font="CourierNew, monospace"].[/font][color="#000000"][font="CourierNew, monospace"]currentTimeMillis[/font][color="#666600"][font="CourierNew, monospace"]()[/font][font="Arial"] on the android. If it's low enough, you'll get wonky results.[/font]
[/quote]

Thanks for the reply.

I have sinced switched over to System.nanoTime() which seems to be a higher resolution.
At any rate, I have found this article:
http://gafferongames.com/game-physics/fix-your-timestep/

and after refactoring me code, I have this:



private final float tick = 0.02f;
private float tickTime = 0;
private float currentTime = 0;


public void onDrawFrame(GL10 gl)
{
float newTime = System.nanoTime()/1000000000.0f;
Time.deltaTime = newTime - currentTime;

currentTime = newTime;

tickTime += Time.deltaTime;

while(tickTime > tick)
{
tickTime -= tick;

Log.e("IMPACT", "" + Time.deltaTime);
// TODO Auto-generated method stub
go.transform.position.x += 30 * Time.deltaTime;
go.update();

}


++Time.frameCount;

}


However, although better, things are still pretty jumpy.
I tried playing with the value of tick, but nothing seems to work. :/
Co-founder/Lead Programmer
Bonafide Software, L.L.C.
Fairmont, WV 26554 US
When you use a fixed timestep, you should be using a constant delta time value. Take another look at the article.
I think that you should put in line:

[color=#1C2837][size=2][color=#000000]go[color=#666600].[color=#000000]transform[color=#666600].[color=#000000]position[color=#666600].[color=#000000]x [color=#666600]+=[color=#000000] [color=#006666]30[color=#000000] [color=#666600]*[color=#000000] [color=#660066]Time[color=#666600].[color=#000000]deltaTime[color=#666600];

tick instead of Time.deltaTime.

So it would be:
[size=2][color=#000000]go[color=#666600].[color=#000000]transform[color=#666600].[color=#000000]position[color=#666600].[color=#000000]x [color=#666600]+=[color=#000000] [color=#006666]30[color=#000000] [color=#666600]*[color=#000000] [color="#660066"]tick[color=#666600];

Also, make sure that tickTime is global, i.e. whenever a call to
[color=#1C2837][size=2][color=#000088]public[color=#000000] [color=#000088]void[color=#000000] onDrawFrame[color=#666600]([color=#000000]GL10 gl[color=#666600])[color=#000000] is made tickTime should not be zero, but hold the remaining time from last call.
You're mixing truly frame-rate independent code (what you're trying to do) with fixed-framerate code (from the article).

I'd go back to the original way you were doing it, but store the nanoseconds, not nanoseconds/1000000000, and divide only the delta. You may lose some precision otherwise.

void OnDrawFrame()
{
float newTime = System.nanoTime();
Time.deltaTime = newTime - Time.currentTime;
Time.currentTime = newTime;

go.transform.position.x += 100 * (Time.deltaTime/1000000000.0f);
go.update();
}


My Gamedev Journal: 2D Game Making, the Easy Way

---(Old Blog, still has good info): 2dGameMaking
-----
"No one ever posts on that message board; it's too crowded." - Yoga Berra (sorta)


You're mixing truly frame-rate independent code (what you're trying to do) with fixed-framerate code (from the article).

I'd go back to the original way you were doing it, but store the nanoseconds, not nanoseconds/1000000000, and divide only the delta. You may lose some precision otherwise.

void OnDrawFrame()
{
float newTime = System.nanoTime();
Time.deltaTime = newTime - Time.currentTime;
Time.currentTime = newTime;

go.transform.position.x += 100 * (Time.deltaTime/1000000000.0f);
go.update();
}


So, am I safe in assuming that the above method should be used for rendering, while the fixed framerate code (from the article) should be used for physics calculations?
Co-founder/Lead Programmer
Bonafide Software, L.L.C.
Fairmont, WV 26554 US
Well, after doing what you siad, everything seems to be working correctly. In fact, even if I divide by 1 billion immediatley instead of doing it when multiplying by deltaTime, it still works. Apparently I forgot to test System.nanoTime() wiht my initial implementation.

Here is my final code in case anyone can use it.

Time class


public class Time
{
public static float deltaTime = 0; //time it took to complete last frame
public static long frameCount = 0; // Number of rendered frames
public static float fixedTime = 0; //The time that the last fixed update was called
public static float fixedDeltaTime = 0.1f; //The interval, in seconds, at which fixed updates are performed
public static float maxDeltaTime = 0.25f; //The maximum time that a frame can take for fixed updates
}


frame update:


private float currentTime = 0;
private float frameTime = 0;
private float accumulator = 0.0f;


public void onDrawFrame(GL10 gl)
{
float newTime = System.nanoTime() / 1000000000.0f;
Time.deltaTime = frameTime = newTime - currentTime;

if(frameTime > Time.maxDeltaTime)
frameTime = Time.maxDeltaTime;

currentTime = newTime;

accumulator += frameTime;

while(accumulator > Time.fixedDeltaTime)
{
//Perform Fixed Updates here
accumulator -= Time.fixedDeltaTime;
}

//Perform all non-physics-related updates here

++Time.frameCount;

}


Feel free to make suggestions on ways to improve it.
Co-founder/Lead Programmer
Bonafide Software, L.L.C.
Fairmont, WV 26554 US

Well, after doing what you siad, everything seems to be working correctly. In fact, even if I divide by 1 billion immediatley instead of doing it when multiplying by deltaTime, it still works. Apparently I forgot to test System.nanoTime() wiht my initial implementation.



Well, that makes sense. I figured the nanosecond implementation would've worked, but suggested a way to get better precision. BTW, you WILL get better precision if you stall the divide until after computing the delta in nanoseconds, but it really shouldn't matter much.

My Gamedev Journal: 2D Game Making, the Easy Way

---(Old Blog, still has good info): 2dGameMaking
-----
"No one ever posts on that message board; it's too crowded." - Yoga Berra (sorta)

This topic is closed to new replies.

Advertisement