Reputation: 89
I am currently making a game where you drive a tank and am currently working on the player class. I want the tank to have inertia for a tiny bit of realistic movement. I have this issue where the speed of my tank isn't topping out at the limit I'm setting. What is strange is that the angle velocity part works great as far as I can tell. Both chunks use the same logic. Right now the tank velocity will max out starting at 1.6, then somewhere between 2 and 3, then 5 and 6, every time you click backwards/forwards.
Here is the code:
final class Player extends GameObject {
private static final double ANGLE_VELOCITY_MAX = Math.PI / 60, ANGLE_VELOCITY_STEP = Math.PI / 900,
ACCELERATION_STEP = .1, ACCELERATION_MAX = 1;
private double angle = 0, angleVelocity = 0, speed = 0, acceleration = 0;
@Override
public final void tick() {
if (gc.getKey(KeyEvent.VK_W) && speed < ACCELERATION_MAX)
if (acceleration + ACCELERATION_STEP > ACCELERATION_MAX)
acceleration = ACCELERATION_MAX;
else
acceleration += ACCELERATION_STEP;
else if (gc.getKey(KeyEvent.VK_S) && speed > -ACCELERATION_MAX)
if (acceleration - ACCELERATION_STEP < -ACCELERATION_MAX)
acceleration = -ACCELERATION_MAX;
else
acceleration -= ACCELERATION_STEP;
else if (Math.abs(acceleration) < ACCELERATION_STEP)
acceleration = 0;
else
acceleration -= Math.signum(acceleration) * ACCELERATION_STEP;
if (gc.getKey(KeyEvent.VK_D) && angleVelocity < ANGLE_VELOCITY_MAX)
if (angleVelocity + ANGLE_VELOCITY_STEP > ANGLE_VELOCITY_MAX)
angleVelocity = ANGLE_VELOCITY_MAX;
else
angleVelocity += ANGLE_VELOCITY_STEP;
else if (gc.getKey(KeyEvent.VK_A) && angleVelocity > -ANGLE_VELOCITY_MAX)
if (angleVelocity - ANGLE_VELOCITY_STEP < -ANGLE_VELOCITY_MAX)
angleVelocity = -ANGLE_VELOCITY_MAX;
else
angleVelocity -= ANGLE_VELOCITY_STEP;
else if (Math.abs(angleVelocity) < ANGLE_VELOCITY_STEP)
angleVelocity = 0;
else
angleVelocity -= Math.signum(angleVelocity) * ANGLE_VELOCITY_STEP;
if (--treadCooldown <= 0) {
if (++treadIndex >= treads.length)
treadIndex = 0;
treadCooldown = TREAD_COOLDOWN;
}
angle += angleVelocity;
speed += acceleration;
location.translate(Math.cos(angle) * speed, Math.sin(angle) * speed);
}
Upvotes: 0
Views: 74
Reputation: 1778
My guess is that you ought introduce some limit for speed
independent of ACCELERATION_MAX
, edit the first if
s to something like:
if (gc.getKey(KeyEvent.VK_W) && acceleration < ACCELERATION_MAX)
...
else if (gc.getKey(KeyEvent.VK_S) && acceleration > -ACCELERATION_MAX)
...
and at the end ensure speed
is within acceptable limits.
BTW:
I have to admit your code above is really hard to read (let alone reason about) for me - I suggest reorganising to something like:
@Override
public final void tick() {
if (gc.getKey(KeyEvent.VK_W)) accelerate(ACCELERATION_STEP);
else if (gc.getKey(KeyEvent.VK_S)) accelerate(-ACCELERATION_STEP);
else accelerate(- Math.signum(acceleration) * ACCELERATION_STEP);
// etc.. you get the idea
}
private void accelerate(double delta) {
setAcceleration(acceleration +delta);
}
private void setAcceleration(double value) {
acceleration = roundToZero(constrain(value, -ACCELERATION_MAX, ACCELERATION_MAX), ACCELERATION_STEP);
}
private static double constrain(double value, double min, double max) {
return value > max ? max : (value < min ? min : value);
}
private static double roundToZero(double value, double radius) {
return Math.abs(value) < radius ? 0 : value;
}
Disclaimer: did not test the above, nor tried to compile it.
Upvotes: 1