简体   繁体   中英

Java “Asteroids” Like Game - Slowing Down Ship

So I have a Java swing application wherein there is a spaceship that gets the angle of rotation and then accelerates in that direction (rotates on its on axis and moves where the front of the ship is). The thing I was having trouble with was getting the ship to decelerate when it points in the opposite direction from its previous direction.

What Happens and what I need to fix

If you look at the image, you'll see that when I try to compensate for my velocity by turning in the completely opposite direction, the speed increases, and what I need to do is have a way to decrease the speed if the ship is compensating for its previous speed.

Example1:

import java.util.Set;

/**
* Created by griffin on 12/7/2015.
*/
public class Example1 extends JPanel {

public enum Input {
    ROTATE_LEFT,
    ROTATE_RIGHT,
    UP,
    DOWN
}

private final int B_WIDTH = 640;
private final int B_HEIGHT = 480;
private Set<Input> inputs;

Ship player = new Ship(320, 240);

public Example1() {
    initExample1();
}

private void initExample1() {
    inputs = new HashSet<>(25);
    setFocusable(true);
    setBackground(Color.BLACK);
    setPreferredSize(new Dimension(B_WIDTH, B_HEIGHT));

    addKeyBinding("rotate-left", KeyEvent.VK_A, Input.ROTATE_LEFT);
    addKeyBinding("rotate-right", KeyEvent.VK_D, Input.ROTATE_RIGHT);
    addKeyBinding("up", KeyEvent.VK_W, Input.UP);
    addKeyBinding("down", KeyEvent.VK_S, Input.DOWN);

    Timer timer = new Timer(40, new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent actionEvent) {
            if (inputs.contains(Input.ROTATE_LEFT)) {
                player.angle -= 5;
            }

            if (inputs.contains(Input.UP)) {

                player.thrust = true;
                player.moveForwards();
            }
            else
                player.moveForwards();

            if (inputs.contains(Input.ROTATE_RIGHT)) {
                player.angle += 5;
            }

            player.checkAngle();
            player.screenWrap();

            repaint();
        }
    });
    timer.start();
}


public void paintComponent(Graphics g) {
    super.paintComponent(g);
    Graphics2D g2d = (Graphics2D) g;
    g2d.setColor(Color.WHITE);
    g2d.drawString("Speed " + (int) player.speed, 15, 15);
    AffineTransform old = AffineTransform.getTranslateInstance(player.x, player.y);
    old.rotate(Math.toRadians(player.angle), player.getWidth() / 2, player.getHeight() / 2);
    g2d.setTransform(old);
    g2d.drawImage(player.ship, 0, 0, this);

    Toolkit.getDefaultToolkit().sync();
}

private void addKeyBinding(String name, int keyCode, Input input) {
    InputMap inputMap = getInputMap(WHEN_IN_FOCUSED_WINDOW);
    ActionMap actionMap = getActionMap();

    inputMap.put(KeyStroke.getKeyStroke(keyCode, 0, false), name + ".pressed");
    actionMap.put(name + ".pressed", new InputAction(input, true));

    inputMap.put(KeyStroke.getKeyStroke(keyCode, 0, true), name + ".released");
    actionMap.put(name + ".released", new InputAction(input, false));
}

private class InputAction extends AbstractAction {

    private Input input;
    private boolean pressed;

    public InputAction(Input input, boolean pressed) {
        this.input = input;
        this.pressed = pressed;
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if (pressed) {
            inputs.add(input);
        } else {
            inputs.remove(input);
        }
    }
}
}

Ship:

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;

/**
* Created by griffin on 12/7/2015.
*/
public class Ship {
float directionX, directionY;
boolean thrust = false;
int x, y;
float speed = 1;
int angle = 0, vAngle = 0;

BufferedImage ship;
private String path = "rocketc.png";

public Ship(int x, int y) {
    this.x = x;
    this.y = y;
    getImage();
}

private void getImage() {
    try {
        ship = ImageIO.read(new File(path));
    } catch (Exception e) {
        e.printStackTrace();
    }
}

public int getWidth() {
    return ship.getWidth();
}

public int getHeight() {
    return ship.getHeight();
}

public void moveForwards() {

    directionX = (float) (Math.cos(Math.toRadians(vAngle))) * speed;
    directionY = (float) (Math.sin(Math.toRadians(vAngle))) * speed;

    if (thrust) {
        speed++;

        vAngle = angle;
        thrust = false;
    }

    x -= directionX;
    y -= directionY;

}

    public void checkAngle () {

        if (angle > 360) {
            angle = 0;
        }
        if (angle < 0) {
            angle = 360;
        }
    }


    public void screenWrap () {
        if (x > 640) {
            x = 0;
        }

        if (x < 0) {
            x = 640;
        }

        if (y > 480) {
            y = 0;
        }

        if (y < 0) {
            y = 480;
        }
    }
}

You've probably figured this out by now, but you're not setting player.thrust back to false when you're checking if the up key is pressed.

if (inputs.contains(Input.UP)) {
    player.thrust = true;
    player.moveForwards();
}
else{
    player.thrust = false; // added this line
    player.moveForwards();
}

Also, if you want drag (that is, deceleration when the up key is not pressed), in Ship.moveForwards() you can decrement speed :

if (thrust) {
    speed++;

    vAngle = angle;
    thrust = false;
}
else{ // added this block
    speed--;
}

You can fiddle with incrementing / decrementing speed by different values to get different acceleration / drag.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM