2D Physics -- applying friction to masses

Started by
1 comment, last by PlasticineGuy 12 years, 9 months ago
I've been trying to make a simple red box that speeds up as you hold arrow keys and slows down to a stop when you release. To do this I've been reading through one of NeHe's tutorials, and here's what I've come up with so far:
class Mass
{
public:
Mass (double mass = 1, const Vector2D& friction = 0): m(mass), f(friction) {}

Vector2D get_pos () const { return pos; }

void apply (Vector2D force)
{
this->force += force;
}

void reset ()
{
force.x = 0;
force.y = 0;
}
void simulate (long double dt)
{
vel += (force / m) * dt;
if (vel != 0) {
vel -= f * dt;
}
pos += vel * dt;
}

private:
double m;
Vector2D f;
Vector2D pos;
Vector2D vel;
Vector2D force;
};
Vector2D is a simple implementation of a vector that defines all the necessary operators, adapted from the tutorial. My game code looks like this:

Mass obj(1, Vector2D(0.5, 0.5));
double dt = 0.1 / 60;

while (!done) {
obj.reset();

if (myWin.checkKey(VK_RIGHT)) { // checks if a given key was pressed.
obj.apply(Vector2D(4, 0));
}

obj.simulate(dt);

displayScene(myWin, (float)obj.get_pos().x, (float)obj.get_pos().y); // implementation not important
}
Now my issue is that once the object starts moving right, it slows down until it stops, then begins moving left. I'm sure it's to do with my implementation of friction:
if (vel != 0) {
vel -= f * dt;
}
It doesn't stop subtracting once velocity reaches 0 because it's never precisely 0. It also would not work correctly if I tried to move my object left. However, I'm not really sure how to approach this problem. Can anybody with more game programming experience give me a hand?
Thanks for your time.

Edit: I found a solution:
vel /= 1 + f * dt;Simple :).
Advertisement
Friction is a force, so it should not be acting on velocity directly as you have it. (vel /= 1 + f * dt;)? And I don't know what the /= is supposed to accomplish.

Don't check your value against *exactly* zero, rather...
if( abs(Velocity) > 0 )
frictionForce = -Velocity.unit * someScalarValue;

This says, "if my speed (velocity implies direction) is bigger than nothing, then lets add friction"
-Velocity.unit: "Friction will act in the opposite direction of my velocity, to slow us down" (Unit implies a vector of length 1.0)
someScalarValue "Friction is effected by things like materials, temperature, etc"

Sum the value of this friction force along with any other forces. Now multiply this sum by InvertedMass.

Now apply that acceleration to your velocity.

This implementation may still weeble wobble back and forth around zero speed, depending on integrator behavior.
[font="Arial"]The idea was that it would decrease over time regardless of sign, but your method works better. Thanks for the tip.
There is a slight wobble that can be noticed in the value of velocity, but it's unnoticable on any reasonable delta times.
Here's the code:
void simulate (long double dt)
{
Vector2D friction = -vel.unitise() * f; // unitise returns a unit vector
apply(friction);

vel += (force / m) * dt;

pos += vel * dt;
}


The integrator is a simple Euler integration. I've read Integration Basics, but been unable to work out how to implement acceleration as a function (any tips there?). I'm not terribly knowledgable about maths or physics.

Edit: After messing around a bit more I figured out how to implement RK4 integration. This together with correct interpolation has completely eliminated any visible roughness or jittering.
[/font]

This topic is closed to new replies.

Advertisement