Nisse
Nisse

Reputation: 47

Java/Slick2D Movement woes (Adding motion instead of setting it?)

I recently moved from Gamemaker: Studio to Java and Slick2D. I'm not sure how to describe my problem, but I'll do my best.

In Gamemaker, there was a feature called motion_add which would add motion to an object with the given parameters (speed and direction).

Let's say we have an object moving down at 20 pixels / frame. If you were to reverse that object's angle 180 degrees (so it is now pointing up) and run the motion_add code, it would slow down all the way to 0, then accelerate again. This works very well for floaty space movement (which is what I'm trying to do).

My question is, how do I recreate this? This is my current moving code:

private void doPlayerMovement(Input input, int delta) {
    // Calculate rotation speed
    rotateSpeed = rotateSpeedBase - (speed / 5);
    if (rotateSpeed < 0.1f) { rotateSpeed = 0.1f; }

    // Get input
    if (input.isKeyDown(Input.KEY_A)) {
        // Rotate left
        if (input.isKeyDown(Input.KEY_W)) { rotation -= rotateSpeed * delta; }
        sprite.rotate(-rotateSpeed * delta);
    } 

    if (input.isKeyDown(Input.KEY_D)) {
        // Rotate right
        if (input.isKeyDown(Input.KEY_W)) { rotation += rotateSpeed * delta; }
        sprite.rotate(rotateSpeed * delta);
    } 

    if (input.isKeyDown(Input.KEY_W)) {
        // Accelerate
        speed += acceleration * delta;
    } if (input.isKeyDown(Input.KEY_S)) {
        // Decelerate
        speed -= acceleration * delta;
    } else {
        if (speed > 0) { speed -= friction; }
    }

    // Clamping
    if (speed > maxSpeed) { speed = maxSpeed; } else if (speed < minSpeed) { speed = minSpeed; }
    if (rotation > 360 || rotation < -360) { rotation = 0; }

    // Make sure rotation catches up with image angle, if necessairy
    if (rotation != sprite.getRotation() && input.isKeyDown(Input.KEY_W)) {
        rotation = sprite.getRotation();
    }

    // Update position
    position.x += speed * Math.sin(Math.toRadians(rotation)) * delta;
    position.y -= speed * Math.cos(Math.toRadians(rotation)) * delta;

What happens:

A and D rotate the sprite. If W is pressed (which accelerates the object), it 'steers' the object. If the object's rotation is not the same as the sprite's rotation, the object's rotation will be set to the sprite's rotation and that's where my issue is.

Doing this will result in the object to instantly shoot in the new direction with it's speed not slowing down. How do I make it slow down?

Edit (sort of) I'm sure there must be a name for this, if you were to drive a car at 100 mph, make it turn 180 degrees somehow while it's moving, and hit the gas, it'll slow down and then accelerate again. That is what I am trying to achieve.

Upvotes: 0

Views: 225

Answers (1)

RPresle
RPresle

Reputation: 2561

You must recreate this behaviour. It may be called inertie. You can add a direction vector to your object so you have a movement direction where it is going to and the effective direction where your animation is pointing.

Then, when you change the direction while in movement you have to decelerate before effectively move toward the new direction.

Vector movementVector=...; // choose whatever class you want
Vector pointingVector=...;

if (movementVector.x == -pointingVector.x || movementVector.y == -pointingVector.y) {
    // if pressing W then decelerate
    // if reaching speed == 0 then change movementVector value and accelerate in the other way
}

Upvotes: 1

Related Questions