2
\$\begingroup\$

So I'm not looking for anything realistic like a physics engine, just want to say that first. I'm working on a simple top-down game and I'm trying to get friction working with deltaTime.

This was my old code:

friction = Math.pow(0.99f, deltaTime * maxFPS);

This worked well and I applied the friction each frame. However, I need to refactor this code since I do not know what the possible maxFPS will be (it could be 30, 60, 120 - it depends on the device limitations).

So here's my new code:

friction = Math.pow(0.6f, deltaTime);

This eliminates the need to know the maxFPS and gives me (roughly) the same output value to apply each frame.


My issue is this: I do not just set the friction to a static value, it changes depending on other factors.

So with my old code, for example, the value I would raise to a power to get friction would range anywhere from 0.6f to 1.0f.

With the new code, I have to use different values since the power is different, so the new range would be 0.0000000000001f to 1.0f.

This just doesn't seem (and feel, when playing the game) right. The range is way too big and from 0.2 - 1.0f the results are all nearly the same value (0.98+, very "slippery" friction) - it doesn't seem like a linear gradient (if that makes sense) the way 0.6f - 1.0f with my old method was.

Just wondering what the common method is to implement frame-independent friction, if I'm doing it right and if there is anything I can do to get the same "feel" I was getting before.

\$\endgroup\$
  • \$\begingroup\$ Can you explain how you then transform the value of friction into a force or a velocity change? Formulas like Math.pow(0.6f, deltaTime) can be correct but it all depends on how friction is applied. \$\endgroup\$ – sam hocevar Dec 14 '13 at 18:13
1
\$\begingroup\$

I don't know what your simple physics looks like, but if you're making a simple top-down shooter you probably have position, velocity, and acceleration, right?

In these terms, you would do this every frame if deltaTime returns number of milliseconds in between frames:

pos += vel * deltaTime / 1000;
vel += accel * deltaTime / 1000;

That gets your objects moving in a reasonable manner.

I've found that implementing friction in these systems as a drag on velocity in the absence of acceleration "feels" right. It's easy to reason about, easy to calculate by hand, and makes a sensible relation right back to velocity:

if (accel == 0) {
  if (vel - friction > 0) {
    vel -= friction;
  } else {
    vel = 0;
  }
}

You'd of course have to check for negative and positive and for x-axis and y-axis. I left all that out to simplify the sample code.

One thing to be careful of with this method: make sure to cap deltaTime to something reasonable, like 50 milliseconds, otherwise your velocities will go insane under a big time step.

\$\endgroup\$
  • \$\begingroup\$ R. Deckers and yourself provided nearly the same answer, appreciate it, using addition/subtraction instead of multiplying the friction is just what I needed. \$\endgroup\$ – Ralph23 Dec 18 '13 at 19:26
3
\$\begingroup\$

I would highly recommend that you decouple your physics (even if very simple) time-step from your frame rate. It is much easier to think about and more predictable. Also, if you are doing simple Euler integration, then it is best to keep the physics time step very small to keep the inevitable errors as small as possible. If your physics calculations are inexpensive, then a small enough time-step (several per frame) will avoid the need to interpolate the values from adjacent time-steps too.

\$\endgroup\$
2
\$\begingroup\$

To add to D. Hayes answer (I can not comment yet I'm afraid). The physically correct friction for objects sliding on a surface is simply a constant, say 'fr', working opposite to the direction of movement (source: http://faculty.wwu.edu/~vawter/physicsnet/topics/Dynamics/Forces/FrictionalForce.html). So

if(vel > 0)
 vel -= fr*dt
else if(vel <0)
 vel += fr*dt
vel += accel*dt;

for objects moving trough a medium (water, air) the friction is linear in the velocity, or quadratic at high speeds.(source: http://hyperphysics.phy-astr.gsu.edu/hbase/airfri.html) so

vel -= fr*v*dt;
vel += accel*dt;

or

vel -= fr*v*v*sign(v)*dt;
vel += accel*dt
\$\endgroup\$
  • \$\begingroup\$ sorry man this is not physically correct, friction is not constant, friction changes as the object velocity changes which lead us to differential equation. Friction factor is constant but that's different. but anyway you don't need physically correct simulation for a game. \$\endgroup\$ – concept3d Dec 14 '13 at 17:58
  • \$\begingroup\$ Sliding friction is independent of velocity, it is given by F = mu*N, where mu is a coefficient dependent on the two materials and N is the normal force. Source: faculty.wwu.edu/~vawter/physicsnet/topics/Dynamics/Forces/… \$\endgroup\$ – R.Deckers Dec 14 '13 at 18:59
  • \$\begingroup\$ this is a simplification. yet enough for a game \$\endgroup\$ – concept3d Dec 14 '13 at 19:41
  • \$\begingroup\$ While others may be stating this isn't 100% accurate, I appreciate all of your input and really like this solution (basically, using addition/subtraction when implementing friction, not multiplication). It seems to solve my issue while keeping the basic simplicity I require, thanks! \$\endgroup\$ – Ralph23 Dec 18 '13 at 19:25
1
\$\begingroup\$

If you're simulating your physics in fixed steps (say your game runs at variable fps but physics is at 15fps), then you could add a callback or function that is called before each physics 'tick'. This way any forces are applied evenly regardless of what your logic is running at.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.