1
\$\begingroup\$

So I have a little game which works with small steps, however those steps vary in time, so for example I sometimes have 10 Steps/second and then I have 20 Steps/second. This changes automatically depending on how many steps the user's computer can take. To avoid inaccurate positioning of the game's player object I use y=v0*dt+g*dt^2/2 to determine my objects y-position, where dt is the time since the last step, v0 is the velocity of my object in the beginning of my step and g is the gravity. To calculate the velocity in the end of a step I use v=v0+g*dt what also gives me correct results, independent of whether I use 2 steps with a dt of for example 20ms or one step with a dt of 40ms.

Now I would like to introduce air drag. For simplicity's sake I use a=k*v^2 where a is the air drag's acceleration (I am aware that it would usually result in a force, but since I assume 1kg for my object's mass the force is the same as the resulting acceleration), k is a constant (in this case I'm using 0.001) and v is the speed.

Now in an infinitely small time interval a is k multiplied by the velocity in this small time interval powered by 2. The problem is that v in the next time interval would depend on the drag of the last which again depends on the v of the last interval and so on... In other words: If I use a=k*v^2 I get different results for my position/velocity when I use 2 steps of 20ms than when I use one step of 40ms.

I used to have this problem for my position too, but adding +g*dt^2/2 to the formula for my position fixed the problem since it takes into account that the position depends on the velocity which changes slightly in every infinitely small time interval.

Does something like that exist for air drag too? And no, I dont mean anything like Adding air drag to a golf ball trajectory equation or similar, for that kind of method only gives correct results when all my steps are the same. (I hope you can understand my intermediate english, it's not my main language so I would like to say sorry for all the silly mistakes I might have made in my question)

\$\endgroup\$

2 Answers 2

0
\$\begingroup\$

There is a similar expression for drag as well, and it is obtained in the same way: by solving the differential equation v'=kv². It yields v=v0 / (1 - k t v0). Note that coefficient k needs to be a negative number, because drag accelerates against the direction of the velocity. Assuming the coefficient does not change over time, the resulting velocity is independent of the timestep.

Though the calculated velocity might be accurate at every step, by numerical integration, the position is not, but since v(t) is a known function, we can integrate analytically too: x = x0 + ln(1 - k t v0) / -k.

\$\endgroup\$
4
  • \$\begingroup\$ This is more like what I was searching for than the other answer, however I don't see g, the gravity, in your formulas. How would I put that into those formulas? \$\endgroup\$
    – Wingblade
    Jul 4, 2012 at 15:17
  • \$\begingroup\$ Or can I simply attach my '+g*v^2/2' to that? I dont think tough... \$\endgroup\$
    – Wingblade
    Jul 4, 2012 at 15:24
  • \$\begingroup\$ Also there is a little problem with the ln(), if 1-ktv0 is smaller than 0 it's a ln of a negative number, what doesn't work. EDIT: Nevermind, since k is negative that will never happen... \$\endgroup\$
    – Wingblade
    Jul 4, 2012 at 18:43
  • \$\begingroup\$ As gravity is an independent force, you can simply add its component to the velocity, i.e.: v=[v0/(1-k t v0)] + g t, and as integration is a linear operation, you can simply add the integrated second term to the position: x = x0 + [ln(1-k t v0)/-k] + [½ g t²] \$\endgroup\$ Jul 4, 2012 at 20:03
1
\$\begingroup\$

It seems to me that the major problem you have is that your physics cannot be interpolated linearly, as you'd except. Because the air drag depends on the speed of the last interval, it has to be run at the same framerate constantly.

A good article on framerate is Fix Your Timestep!.

What I would do in your case is to run the physics simulation at a fixed framerate, for instance 30 frames per second, but run the rendering as fast as possible.

Here's the main loop I use for almost all my games:

g_TimeStart = GetTickCount() - (int)(g_FramePhysics + 1);

do 
{
    g_TimeCurrent = GetTickCount();
    g_TimeStack += (float)g_TimeCurrent - (float)g_TimeStart;
    g_TimeStart = g_TimeCurrent;

    // when debugging, you'll end up with a gigantic stack of
    // frames to simulate, which is annoying
    // this puts a cap on the amount of frames to simulate
    if (g_TimeStack > g_FramePhysicsMax)
    {
        g_TimeStack = g_FramePhysicsMax;
    }

    while (g_TimeStack > g_FramePhysics)
    {
        glfwPollEvents();

        // to slow down the physics, we change this value
        g_Scene->Update(Scene::s_DeltaTime);

        RenderManager::Get().ClearInput();

        g_TimeStack -= g_FramePhysics;
    }

    // render scene

    g_Scene->Render();

    // render interface

    RenderInterface();

    // swap

    glfwSwapBuffers();
}
while (g_WindowOpen);

A mistake I made in the past is to have delta time be something like 1/30. The correct value is 1 for a simulation that runs at normal speed. Thus, to slow it down to 15 fps, you'd input a value of 0.5 into your physics simulation. The physics simulation will still run at a fixed 30 frames per second, but each frame will "weigh" less overall. However, you'll have to be careful with the delta time and figure out where you need to apply it in your physics simulation.

Are you updating a position with a velocity? Update the velocity with the delta time.

Are you updating a position with a velocity, but the acceleration of the velocity changes? Update the acceleration with the delta time, but not the velocity.

\$\endgroup\$
3
  • \$\begingroup\$ To my understanding your code acctually calculates a frame for every tick, eventough the game loop only runs like once every e.g. 30 ticks. In that case your game still acts as tough it would make a step every tick, eventough it acctually makes a step every 30 ticks, but one that acts as tough it was 30 individual frames? Am I getting this right. \$\endgroup\$
    – Wingblade
    Jul 4, 2012 at 9:13
  • \$\begingroup\$ The idea is to interpolate between physics frames. Because the physics simulation happens at a fixed framerate, it doesn't get out of sync with the rendering. This also means that the simulation can be slowed down or sped up, without affecting the simulation itself. But only as long as the delta time variable is used at the correct places in the simulation. \$\endgroup\$
    – knight666
    Jul 4, 2012 at 9:25
  • \$\begingroup\$ I think I get your idea now... However I am worried about the "spiral of death" mentioned in the article you provided. I'll see what I can do about that. Thank you for your help! \$\endgroup\$
    – Wingblade
    Jul 4, 2012 at 9:30

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .