java - 为什么我的玩家在释放箭头键后继续移动(非常缓慢)?

标签 java swing game-physics

我正在使用 Swing 开发我的第一个 2D Java 游戏,并且遇到了一个奇怪的错误。 首先是相关代码:

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;
    }

}

(请原谅草率的代码。) 小红方 block 玩家移动得很好,但当我释放箭头键时,玩家以 20(此时为任意单位)的速度移动(向下或向右),即每秒几个像素。 我认为这与摩擦有关,但我不确定。

最佳答案

您永远不会重置 accelXaccelY,因此加速度会持续应用于各帧。你的玩家实际上应该加速,但我认为摩擦力可能以某种方式相互作用以产生缓慢的运动。

关于java - 为什么我的玩家在释放箭头键后继续移动(非常缓慢)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20204067/

相关文章:

java - 在 ItemListener 中显示消息对话框会阻止选择复选框

java - 从 Java 中的 JPopupMenu 操作监听器获取目标

C++ 时间测量看起来太慢

javascript - 为什么我不能让背景中的山脉以视差方式移动?

java - 如何让我的代码继续编码直到输入 "0"

java - com.mysql.jdbc.exceptions.jdbc4.CommunicationsException:通信链接失败

java - 按 JPA 标准查询中的聚合字段过滤

java - 获取异常-java.lang.IllegalStateException : Error: drawImage is not allowed within a text block

Java Swing ;两个类,if 语句和新的 actionlisteners 放在哪里?

ios - 如何将碰撞检测设置到我想要的位置?