Ok, so I am making a first person shooter game and I am currently working on movement that looks and feels good. I want to incorporate acceleration based movement for the player so that he has to accelerate to max speed and decelerate to minimum speed. Acceleration will happen when you have the key pressed and deceleration will happen when you let go of that key. The problem is that there are some instances where you switch from moving forward to moving backward where no deceleration is needed because you could potentially be moving at double speed in the reverse if you did. Does anyone have a good implementation of how to accomplish acceleration based movement that works well?
-
\$\begingroup\$ When the key is down you could just add an x amount of velocity(building up from zero to max velocity) to your position. When you hit the backward key the velocity decreases going into the minus zero. You're still adding the velocity to your position. Once it goes into a negative number, the addition of this velocity turns into a subtraction. Giving the effect that your character is decelerating first and then walks backward. When no keys are pressed you can interpolate towards zero. This could also be done by multiplying by a number smaller than 1 i.e. 0.98f Giving the effect of friction. \$\endgroup\$– SidarSep 4, 2012 at 20:22
-
\$\begingroup\$ Just as a note because it's somewhat unclear from the question but deceleration should go toward 0. You'll still want deceleration toward 0 when you stop moving backward, None at all would cause you to drift backward forever. \$\endgroup\$– LuninSep 4, 2012 at 21:14
-
\$\begingroup\$ @lunin; That's why I suggest multiplying the velocity by a number smaller than 1 when no key is pressed. Because the velocity becomes smaller and smaller on every step eventually hitting zero. A fake friction if you will. \$\endgroup\$– SidarSep 5, 2012 at 4:05
-
\$\begingroup\$ @Sidar So you did! That's what I get for commenting before fully reading all the other comments \$\endgroup\$– LuninSep 6, 2012 at 17:20
-
\$\begingroup\$ @Lunin yeah, I too draw conclusions too fast...we need to stop doing that =P \$\endgroup\$– SidarSep 6, 2012 at 19:16
1 Answer
There's something weird about your concept of the issue since you say, "could potentially be moving at double speed in the reverse." This should not be the case with an acceleration-based solution.
You will have a double playerVelocity
value in your Player class. To keep it simple for now, imagine just forward/backward velocity. Every frame, you add your acceleration value (PLAYER_ACCELERATION
) to the player's velocity until it reaches a maximum - the speed at which you generally want the player to run (PLAYER_MAX_SPEED
). This should only take a handful of frames unless you want the controls to feel very "floaty". (You don't for a modern FPS.)
If the player reverses direction, you add negative acceleration. If they are moving forward at full speed and reverse direction, it will take them twice as long to get to "full speed reverse" than it does from standing still.
If the player releases all buttons, you add acceleration towards zero. The player will slow down until they stop.
An implementation:
final PLAYER_MAX_SPEED = 1.0f;
final PLAYER_ACCELERATION = 0.2f;
double playerVelocity = 0.0f;
public void update() { // Called every frame, and assuming constant fps
if (forward_button_down) {
// The player is holding the "move forward" button
playerVelocity += PLAYER_ACCELERATION;
if (playerVelocity > PLAYER_MAX_SPEED) {
playerVelocity = PLAYER_MAX_SPEED;
}
} else if (backward_button_down) {
// The player is holding the "move backward" button
playerVelocity -= PLAYER_ACCELERATION;
if (playerVelocity < -PLAYER_MAX_SPEED) {
playerVelocity = -PLAYER_MAX_SPEED;
}
} else {
// Neither forward nor backward pressed
if (playerVelocity < 0) {
playerVelocity += PLAYER_ACCELERATION;
if (playerVelocity >= 0) {
playerVelocity = 0.0f;
}
} else {
playerVelocity -= PLAYER_ACCELERATION;
if (playerVelocity <= 0) {
playerVelocity = 0.0f;
}
}
}
Another thing you'll probably want to do is make the player accelerate much more quickly toward zero than they accelerate beyond zero, otherwise your character will feel unresponsive.
If you use something like this for forward/backward, and another variable for left/right, you'll have to limit the combined speed (bust out your geometry), otherwise your character will move diagonally-forward faster than they move only-forward.