Wednesday, June 24, 2015

physics - Frame-rate independent friction on movement in 2d game



I have been trying to implement a simple physics system for a 2D space game I am making. I have it pretty much working, but I have encountered an issue with the way I apply friction. I have tried several different ways of solving it, with different guides found online, but my math skills are lacking and it's difficult for me to translate the solutions to fit my problem.


I made a unit test that shows my problem:


            //Simulate a low FPS.
//Accelerate body1 with 100 pixels/second, for a deltaTime of 1 (A single frame that took 1 second)
body1.accelerate(100, 1);
//Performe the physics with the dame deltaTime.
body1.doPhysics(1);

//Simulate a higher fps.
//Accelerate body2 10 times, with 100 pixels/second for a deltaTime of 0.1 (A single frame that took 1/10'th of a second.

for(int j=0; j< 10; j++) {
body2.accelerate(100, 0.1);
body2.doPhysics(0.1);
}

Debug.Log("Straight movement result "+body1.getPosition()+" --- "+body2.getPosition());

Which gives the result: "Straight movement result [0.0, 50.0] --- [0.0, 39.31200662855]"


My acceleration does not seam to be a problem. I have a unit test like the other one, to test the acceleration, and it shows no problems.


public void accelerate(double acceleration, double deltaTime) {

Vector2f accel = new Vector2f(0, (float)(acceleration));

//If power is negative, we want to go backwards.
if(acceleration < 0)
accel.setTheta(angle+90 - 180);
else
accel.setTheta(angle+90);

velocity.x += (accel.x * deltaTime);
velocity.y += (accel.y * deltaTime);

}

In the doPhysics method, is where I calculate the friction. If I remove the friction calculations, the two values printed from the unit test are equal.


private static final float friction = 1.0f;//0.96f;

private void doPhysics(double deltaTime) {
//Save the velocity before applying friction.
Vector2d velBefore = new Vector2d(velocity);

//Then apply friction, with deltaTime.

velocity.x -= (velocity.x * friction) * deltaTime;
velocity.y -= (velocity.y * friction) * deltaTime;

//And then calculate the average of the friction before and after friction and factor in deltaTime
double realVelX = ((velBefore.x + velocity.x) * 0.5) * deltaTime;
double realVelY = ((velBefore.y + velocity.y) * 0.5) * deltaTime;

//Add the calculated velocity.
position.x += realVelX;
position.y += realVelY;

}

I hope someone can see what I am doing wrong. I would really like my physics to be frame-rate independent and simple enough for me to understand.




No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...