【问题标题】:Player not moving in 2D Game玩家在 2D 游戏中不动
【发布时间】:2013-12-12 15:20:09
【问题描述】:

按下某些键时,我似乎无法让我的播放器移动。我进行了一些调试,并在 if 语句中放置了一个System.out.print("Pressed);,用于检查是否按下了某个键,并且每次我按下该键时它都会打印出消息,他们的玩家只是没有移动。有人可以帮忙吗!

这里是 InputHandler 类

public class InputHandler implements KeyListener {

    public InputHandler(Game game) {
        game.addKeyListener(this);
    }

    public class Key {
        private boolean pressed = false;

        public void toggle(boolean isPressed) {
            pressed = isPressed;
        }

        public boolean isPressed() {
            return pressed;
        }
    }

    // public List<Key> keys = new ArrayList<Key>();
    public Key up = new Key();
    public Key down = new Key();
    public Key left = new Key();
    public Key right = new Key();

    public void keyPressed(KeyEvent e) {
        toggleKey(e.getKeyCode(), true);
    }

    public void keyReleased(KeyEvent e) {
        toggleKey(e.getKeyCode(), false);
    }

    public void keyTyped(KeyEvent e) {

    }

    public void toggleKey(int keyCode, boolean isPressed) {
        if (keyCode == KeyEvent.VK_W) {
            up.toggle(isPressed);
        } else if (keyCode == KeyEvent.VK_S) {
            down.toggle(isPressed);
        } else if (keyCode == KeyEvent.VK_A) {
            left.toggle(isPressed);
        } else if (keyCode == KeyEvent.VK_D) {
            right.toggle(isPressed);
        }
    }
}

这里是 Player 类

public class Player extends Mob {

    private InputHandler input;
    private int r = 10;

    public Player(int x, int y, int speed, InputHandler input) {
        super("Player", x, y, 1);
        this.input = input;
        this.x = x;
        this.y = y;
    }

    public boolean hasCollided(int dx, int dy) {
        return false;
    }

    public void update() {
        int dx = 0;
        int dy = 0;

        if (input.up.isPressed()) {
            dy--;
        } else if (input.down.isPressed()) {
            dy++;
        } else if (input.left.isPressed()) {
            dx--;
        } else if (input.right.isPressed()) {
            dx++;
        }

        if (dx != 0 || dy != 0) {
            move(dx, dy);
            isMoving = true;
        } else {
            isMoving = false;
        }

        if (x < r)
            x = r;
        if (y < r)
            y = r;
        if (x > Game.WIDTH - r)
            x = Game.WIDTH - r;
        if (y > Game.HEIGHT - r)
            y = Game.HEIGHT - r;
    }

    public void render(Graphics2D g) {
        g.setColor(Color.BLACK);
        g.fillOval(x - r, y - r, 2 * r, 2 * r);

        g.setStroke(new BasicStroke(3));
        g.setColor(Color.GRAY);
        g.drawOval(x - r, y - r, 2 * r, 2 * r);
        g.setStroke(new BasicStroke(1));
    }
}

这里是 Mob 类,其中包含 move() 方法

    public Mob(String name, int x, int y, int speed) {
        this.name = name;
        this.speed = speed;
    }

    public void move(int dx, int dy) {
        if (dx != 0 && dy != 0) {
            move(dx, 0);
            move(dy, 0);
            numSteps--;
            return;
        }
        numSteps++;

        if (!hasCollided(dx, dy)) {
            if (dy < 0)
                movingDir = 0;
            if (dy > 0)
                movingDir = 1;
            if (dx < 0)
                movingDir = 2;
            if (dx > 0)
                movingDir = 3;

            x += dx * speed;
            y += dy * speed;
        }
    }

    public abstract boolean hasCollided(int dx, int dy);

    public String getName() {
        return _name;
    }
}

【问题讨论】:

    标签: java keylistener


    【解决方案1】:

    Player 类中的 render 方法是从哪里调用的?您是否在某处覆盖了paint(Graphics) 或paintComponent(Graphics)?

    原来 JFrame 没有焦点。一旦聚焦,代码就可以很好地工作。

    【讨论】:

    • 这不是答案。评论会更合适。
    • 我有,但我没有能力发布 cmets,因为我只有 38 分 :(
    • @ZebBarnett 更新发生在游戏类更新和渲染方法中的游戏循环中
    • @zachstarnes 啊,有道理。再看一遍后,我对 Mob 类中的一部分 move 方法感到非常困惑。似乎您正在发生递归情况,但您在第二次递归调用中将 dy 传递到 dx 点。这是故意的吗?
    【解决方案2】:

    这段代码有各种各样的问题,但最紧迫的似乎是对_x和x都有引用。选择一个并让所有方法都使用那个。这可能会有所帮助,但老实说,很难确切地说出要修复什么,也许从更简单的开始?

    【讨论】:

      【解决方案3】:

      我发现您的移动代码有一个错误。你在 if 语句中调用 move(dx, 0)move(dy, 0),如果 both 都不为 0。在随后的递归中,它们都是 0 并且什么都不做。相反,将&amp;&amp; 更改为||

      public void move(int dx, int dy) {
              if (dx != 0 || dy != 0) {
                  move(dx, 0);
                  move(dy, 0);
                  numSteps--;
                  return;
              }
              ...
      }
      

      【讨论】:

      • 我按照你说的改变了操作符,但是玩家仍然不动:(
      • 好的,我还没有真正看过代码。但是,如果 dx 表示 delta x,那么你为什么要做一个 if?只需移动 delta x。碰撞应该会抛出一个错误,也许。
      • @Bucco 的要点是,如果按下两个键,它会一次处理一个键,这样玩家就不会以双倍的速度移动
      • @zachstarnes 我有一个问题 - Mob 类中的 x 和 y 是什么?我看到你有一个 _x 和一个 _y 但在 move 方法的底部我不明白 x,y 是什么。
      • @Bucco x 和 y 是创建生物时的起点,因此玩家从屏幕中间开始,move() 方法改变 x 和 y跨度>
      【解决方案4】:

      这里的代码太多了,对于一个问题来说实在是太多了。

      更好的方法是继续缩小每个班级。具体来说,不要对墙壁进行错误检查。只需移动暴徒/任何东西。如果有问题,那么游戏(?)会抛出错误......

      一般来说,我会说这种方法过度关注“如果会怎样?”问题而不是操纵具有 x,y 坐标系的 2d 地牢的基础知识。

      (只是为了混淆问题,如果它在极坐标中怎么办!?无论如何......)

      在让你的代码运行之后,我继续为你把它放在 github 上:

      https://github.com/THUFIR/Game2D/tree/master/src/genericGame

      随意分叉,请做。 Git 或任何版本控制都可以在您的代码正常工作时真正提供帮助,但是出现了问题......

      这是输出,非常简单:

      thufir@dur:~/NetBeansProjects/Game2D$ 
      thufir@dur:~/NetBeansProjects/Game2D$ java -jar dist/Game2D.jar 
      x   1   y   1
      x   4   y   6
      thufir@dur:~/NetBeansProjects/Game2D$ 
      

      司机:

      package genericGame;
      
      import static java.lang.System.out;
      
      public class Driver {
      
          public static void main(String[] args) {
              Player player = new Player(0, 0, 0);
              player.move(1, 1);
              out.println(player);
              player.move(3, 5);
              out.println(player);
          }
      }
      

      和玩家:

      package genericGame;
      
      import java.awt.BasicStroke;
      import java.awt.Color;
      import java.awt.Graphics2D;
      
      public class Player extends Mob {
      
          private int r = 10;
      
          public Player(int x, int y, int speed) {
              super("Player", x, y);
              this.x = x;
              this.y = y;
          }
      
          public boolean hasCollided(int dx, int dy) {
              return false;
          }
      
          public void update() {
              int dx = 0;
              int dy = 0;
      
              if (input.up.isPressed()) {
                  dy--;
              } else if (input.down.isPressed()) {
                  dy++;
              } else if (input.left.isPressed()) {
                  dx--;
              } else if (input.right.isPressed()) {
                  dx++;
              }
      
              if (dx != 0 || dy != 0) {
                  move(dx, dy);
                  isMoving = true;
              } else {
                  isMoving = false;
              }
      
              if (x < r) {
                  x = r;
              }
              if (y < r) {
                  y = r;
              }
              if (x > Game.WIDTH - r) {
                  x = Game.WIDTH - r;
              }
              if (y > Game.HEIGHT - r) {
                  y = Game.HEIGHT - r;
              }
          }
      
          public void render(Graphics2D g) {
              g.setColor(Color.BLACK);
              g.fillOval(x - r, y - r, 2 * r, 2 * r);
      
              g.setStroke(new BasicStroke(3));
              g.setColor(Color.GRAY);
              g.drawOval(x - r, y - r, 2 * r, 2 * r);
              g.setStroke(new BasicStroke(1));
          }
      }
      

      希望对您有所帮助。请学习 git。

      我会阅读其他答案以找到更好的解决方案,我只是用锤子敲打它,直到它编译完成。方法、类和字段的命名约定、组织和访问级别都是改进的机会。

      【讨论】:

        猜你喜欢
        • 2023-03-22
        • 1970-01-01
        • 2012-03-01
        • 2022-11-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-02-22
        • 1970-01-01
        相关资源
        最近更新 更多