简体   繁体   中英

Why does my player continue to move (very slowly) after releasing the arrow keys?

I'm working on my first 2D Java game using Swing, and I've run into an odd bug. Here's the relevant code, first of all:

GamePanel.java

public class GamePanel extends JPanel implements KeyListener {

    public GamePanel() {
        setPreferredSize(new Dimension(STAGE_WIDTH, STAGE_HEIGHT));

        Thread runner = new Thread(new Runnable() {
            @Override
            public void run() {
                begin();
                long lastUpdate = System.currentTimeMillis();
                while (true) {
                    long elapsed = System.currentTimeMillis() - lastUpdate;
                    repaint();
                    if (elapsed < 16) {
                        try {
                            Thread.sleep(20 - elapsed);
                        } catch (InterruptedException ex) {
                            ex.printStackTrace();
                        }
                    }
                    update((System.currentTimeMillis() - lastUpdate) / 1000.0);
                    lastUpdate = System.currentTimeMillis();
                }
            }
        });
        runner.start();
    }

    //variables
    int bulletVelocity = 10;
    final int STAGE_HEIGHT = 600;
    final int STAGE_WIDTH = 800;
    int playerWidth = 50;
    int playerHeight = 50;

    //lists
    List<Bullet> bulletList = new ArrayList<>();
    List<Enemy> enemyList = new ArrayList<>();

    //objects
    Player player = new Player((STAGE_WIDTH - playerWidth) / 2, (STAGE_HEIGHT - playerHeight) / 2, 0, 0, playerWidth, playerHeight);

    public void begin() {

    }

    public void update(double delta) {
        player.update(delta);
        //System.out.println(delta);
        for (Bullet bullet : bulletList) {
            bullet.update();
        }
        for (Enemy enemy : enemyList) {
            enemy.update(player.getXPos(), player.getYPos());
        }
    }

    @Override
    public void paint(Graphics g) {
        g.setColor(Color.BLACK);
        g.fillRect(0, 0, getWidth(), getHeight());
        g.setColor(Color.RED);
        g.fillRect((int) player.getXPos(), (int) player.getYPos(), player.getWidth(), player.getHeight());
        g.setColor(Color.BLUE);
        for (Bullet bullet : bulletList) {
            g.fillRect((int) bullet.getXPos(), (int) bullet.getYPos(), 10, 10);
        }
        g.setColor(Color.GREEN);
        for (Enemy enemy : enemyList) {
            g.fillOval((int) enemy.getXPos(), (int) enemy.getYPos(), enemy.getWidth(), enemy.getHeight());
        }
    }

    @Override
    public void keyTyped(KeyEvent e) {
    }

    private Set<Integer> keysDown = new HashSet<Integer>();

    @Override
    public void keyPressed(KeyEvent e) {
        if (keysDown.contains(e.getKeyCode())) {
            return;
        }
        keysDown.add(e.getKeyCode());

        if (e.getKeyCode() == KeyEvent.VK_LEFT) {
            player.addAccelX(-1);
        } else if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
            player.addAccelX(1);
        } else if (e.getKeyCode() == KeyEvent.VK_UP) {
            player.addAccelY(-1);
        } else if (e.getKeyCode() == KeyEvent.VK_DOWN) {
            player.addAccelY(1);
        } else if (e.getKeyCode() == KeyEvent.VK_SPACE) {
            Bullet bullet = new Bullet(player.getXPos() + (player.getWidth() / 2), player.getYPos(), bulletVelocity - (player.getYVel() / 4));
            bulletList.add(bullet);
        } else if (e.getKeyCode() == KeyEvent.VK_E) {
            Enemy enemy = new Enemy(100, 100, Math.random() * 3 + .5, 10, 10);
            enemyList.add(enemy);
        } else if (e.getKeyCode() == KeyEvent.VK_A) {
            System.out.println(toDegrees(atan2(player.getYPos() - 0, player.getXPos() - 0)));
        }
    }

    @Override
    public void keyReleased(KeyEvent e) {
        keysDown.remove(e.getKeyCode());

        if (e.getKeyCode() == KeyEvent.VK_LEFT) {
            player.addAccelX(1);
        } else if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
            player.addAccelX(-1);
        } else if (e.getKeyCode() == KeyEvent.VK_UP) {
            player.addAccelY(1);
        } else if (e.getKeyCode() == KeyEvent.VK_DOWN) {
            player.addAccelY(-1);
        }
    }

}

Player.java

public class Player {

    private final double MAX_VELOCITY = 500;
    private final double ACCELERATION = 3000.0;

    //friction is % ? Add that later   
    private final double FRICTION = 400.0;
    private double mass = 10.0;

    private double xPos = 400;
    private double yPos = 200;
    private double xVel = 0.0;
    private double yVel = 0.0;
    private int width = 100;
    private int height = 100;
    private int xDir = 0;
    private int yDir = 0;

    private boolean moving = false;

    private double accelX = 0.0;
    private double accelY = 0.0;

    public Player() {

    }

    public Player(double xPos, double yPos, double xVel, double yVel, int width, int height) {
        this.xPos = xPos;
        this.yPos = yPos;
        this.xVel = xVel;
        this.yVel = yVel;
        this.width = width;
        this.height = height;
    }

    public void update(double delta) {

        this.xVel += accelX * delta;
        this.yVel += accelY * delta;

        if(abs(xVel) > MAX_VELOCITY){xVel = MAX_VELOCITY * xDir;}
        if(abs(yVel) > MAX_VELOCITY){yVel = MAX_VELOCITY * yDir;}

        if(xVel > 0) xVel += -FRICTION / mass;
        if(xVel < 0) xVel += FRICTION / mass;


        //debugging
        //System.out.println(yVel);

        if(yVel > 0) yVel += -FRICTION / mass;
        if(yVel < 0) yVel += FRICTION / mass;

        //System.out.println(yVel);

        //if(!moving){xVel = 0; yVel = 0;}

        this.xPos += this.xVel * delta;
        this.yPos += this.yVel * delta;



    }

    public void setMoving(boolean moving){
        this.moving = moving;
    }

    public void move(double delta) {
        /*
         * Acceleration = Force / Mass
         * Velocity += Acceleration * ElapsedTime (delta)
         * Position += Velocity * ElapsedTime (delta)
         */


    }

    public double getAccel(){
        return ACCELERATION;
    }

    public void addAccelX(int dir) {
        this.accelX += ACCELERATION * dir;
        //this.xDir = dir;
    }

    public void addAccelY(int dir) {
        this.accelY += ACCELERATION * dir;
        //this.yDir = dir;
    }


    public double getXPos() {
        return this.xPos;
    }

    public double getYPos() {
        return this.yPos;
    }

    public double getXVel() {
        return this.xVel;
    }

    public double getYVel() {
        return this.yVel;
    }

    public int getHeight() {
        return this.height;
    }

    public int getWidth() {
        return this.width;
    }

    public void addXPos(int delta) {
        this.xPos += delta;
    }

    public void addYPos(int delta) {
        this.yPos += delta;
    }

    public void addXVel(int delta) {
        this.xVel += delta;
    }

    public void addYVel(int delta) {
        this.yVel += delta;
    }

}

(Please excuse the sloppy code.) The little red square player moves fine, but when I release the arrow keys, the player moves (either down or to the right) with a velocity of 20 (arbitrary units at this point), which comes out to a few pixels/sec. I think that it has something to do with the friction, but I'm not sure.

You never reset accelX and accelY and so the acceleration is continuously applied across frames. Your player should actually be accelerating, but I think that friction may be interacting in some way to create slow movement.

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