Applying Acceleration to a player

Started by
1 comment, last by TiPiou 12 years ago
Im working on a project to basically help myself get better with game physics.

I'm having a problem with adding acceleration to velocity.

I want to move my character around using W A S D keys, but i cant figure out how to get the player to slow down to a stop after i release the key.

I know the code ive written is most likely FAR more than what you need to do this but this is what i've got



// For each key i do something like this
if(KeyDown(keyW))
{
if(Length(player.Acceleration) == 0)
{
// Set acceleration to the direction of the camera
Vector3 camDir = GetCameraDirection();

player.Acceleration.x = camDir.x * playerSpeed;
player.Acceleration.z = camDir.z * playerSpeed;
}
}
else
{
if(player.Acceleration.x > 0)
{
player.Acceleration.x -= playerSpeed;

if(player.Acceleration.x < 0)
player.Acceleration.x = 0;
}
if(player.Acceleration.z > 0)
{
player.Acceleration.z -= playerSpeed*time.GetDeltaTime();

if(player.Acceleration.z < 0)
player.Acceleration.z = 0;
}
}

// Then i update the players position
player.Velocity += player.Acceleration;
player.Position += player.Velocity;



This code works for speeding up and maintaining a constant speed, but when i release the button the player doesn't stop
Advertisement
Why don't you just set acceleration to 0 when a key isn't pressed, rather than subtracting playerSpeed from it and then setting it to 0 if it becomes negative?

Why don't you just set acceleration to 0 when a key isn't pressed, rather than subtracting playerSpeed from it and then setting it to 0 if it becomes negative?

Acceleration of 0 means a constant speed, not a slowdown.

@Muzzy :
First, I don't really understand how you get your current results. From the code I see, when the key is pressed, you set a constant acceleration. Yet you're reporting that you observe a "constant speed", which imho is quite puzzling to begin with (a constant acceleration would mean exactly that : you'd keep accelerating forever).

Second, I fail to see why you would need a different method for handling x and z in the part of your code trying to handle deceleration.


I see two paths here, depending on the kind of "reality" you want to simulate :

First Method : you consider that "pressing the 'W' key" means pressing the gas pedal on a car, and "not pressing the 'W' key" means not pressing the gas pedal of a car.

1) When user presses 'W', set a constant acceleration just as you do now (but either double check your result - or interpretation of the result - or fix the issue that you currently experience a "constant speed" as a result). Ah, and rename that "playerSpeed" constant to something more appropriate, like "playerAcceleration", if you insist on using it as the length of this constant acceleration vector. And also remove that test on Acceleration length, it's not really worth it as things are, and will prevent you from turning around once you work on the other keys tongue.png
2) When not pressing 'W', set acceleration to zero.
3) Whatever the user does with his keys, set a constant friction force opposing your current velocity.
=> When deceleration resulting from force outweights the acceleration from the engine, you will eventually experience a "constant" maximum speed.
=> When not pressing the gas pedal, you will eventually come to an halt.

Second Method : you see "pressing the 'W' key" as actively moving your feets in some kind of I-want-to-go-there fashion (or, once again, pressing the gas pedal on a car), and "not pressing the 'W' key" as actively slowing down those feets (or pressing the brakes on a car).

1) When user presses 'W', set a constant acceleration just as you do now, but also impose a limit on the maximum speed.
2) When user does not press 'W', set a constant deceleration, and clamp your speed to zero when it would try to go backwards.


//
// First method
//
Vector3 camDir = GetCameraDirection();
if (keyDown(keyW)) {
player.Acceleration.x = camDir.x * playerAcceleration;
player.Acceleration.z = camDir.z * playerAcceleration;
} else {
player.Acceleration = nullVector;
if (currentSpeed < minSpeed) {
// when speed becomes too tiny, we can safely assume we have come to an halt.
player.Velocity= nullVector;
}
}
// friction (with the road, against the air, from the engine internals, whatever.) is a force opposing movement.
Vector3 friction = ( - player.Velocity ) * someFrictionFactor;

// a force typically sets an acceleration on an object, in inverse proportion with the object's mass (or weight, if you prefer).
player.Acceleration += friction / playerMass;

player.Velocity += player.Acceleration;
player.Position += player.Velocity;

// *********************

//
// Second method
//
Vector3 camDir = GetCameraDirection();
float currentSpeed = Length(player.Velocity);
if (keyDown(keyW)) {
// restricts the throttle if the player comes close to max speed so that your player cannot go too fast.
float possibleAcceleration = playerAcceleration;
if (currentSpeed + possibleAcceleration > maxSpeed) {
// This part will get tricky once you start messing with the real timing, but let's keep it simple for now.
possibleAcceleration = maxSpeed - currentAcceleration;
}
player.Acceleration.x = camDir.x * possibleAcceleration;
player.Acceleration.z = camDir.z * possibleAcceleration;
} else {
if (currentSpeed > minSpeed) {
player.Acceleration = ( - player.Velocity ) * playerAcceleration;
} else {
// when speed becomes too tiny, we can safely assume we have come to an halt.
player.Acceleration = nullVector;
player.Velocity= nullVector;
}
}
player.Velocity += player.Acceleration;
player.Position += player.Velocity;


As a side note, well... that depends on what you are doing of course, but I would assume you only need position and velocity to be properties of a "player", as you'll need those each frames along with their previous values (note the usage of '+=' in the related operations), but this is not the case for acceleration which could be a local variable of the method.

Follow NeREIDS development on my blog : fa-nacht.rmyzen.net/

This topic is closed to new replies.

Advertisement