【问题标题】:How to do collision detection with many walls (maze)?如何与许多墙壁(迷宫)进行碰撞检测?
【发布时间】:2017-07-03 16:48:49
【问题描述】:

在我的游戏中,玩家在迷宫中导航。我不知道如何对墙壁进行正确的碰撞检测。停留在某个区域很容易进行碰撞检测:

if (x > rightWallX - playerWidth) x = rightWallX - playerWidth;
if (x < leftWallX) x = leftWallX;
//...

但是如何对许多墙壁进行碰撞检测呢?

我可以在不进行更正的情况下进行简单的碰撞检测(例如if (intersecting) return true;),但我无法正确更正。如果我只是存储旧的xy 并重置它们,那么

  1. 对象实际上从未接触过墙壁
  2. 如果物体可以上升但被挡在右边,它就不会上升,它就不会移动。

如何在迷宫中进行碰撞检测?

【问题讨论】:

  • “我可以在不进行校正的情况下进行简单的碰撞检测”好主意;现在添加更正。 “存储旧的 x 和 y 并重置它们”来吧,你可以做得更好:-)
  • @JanDvorak 我还能做什么?我想不出任何其他方式:/
  • 建议 #1:在大多数情况下,重置 either x or y 就足够了。
  • @JanDvorak 但是该对象实际上从未接触过墙壁,它在几个像素之外徘徊。 (这是因为对象不会每刻移动 1 个像素)
  • 建议 #2:您不需要重置该值。改变它足够就足够了。

标签: java collision-detection maze


【解决方案1】:

最简单的方法是,一旦你解决了碰撞检测修复碰撞就是将actor移动到最接近actor所在位置的有效位置不是它碰撞的物体。这假设没有惯性,但对于迷宫类游戏或自上而下的地图爬行游戏来说已经足够了。

如果您想进一步简化计算,您可以限制自己检测更改演员的xy 坐标是否会更好。如果你的actor有一个轴对齐的矩形hit-box并且所有的障碍物也是轴对齐的矩形(最简单的情况),这个假设确实是正确的。然而,在其他一些情况下,结果可能并不令人满意(潜在的神器:滑行对角墙的速度提升 - 在大多数迷宫游戏中并非如此)。

请记住,多个碰撞可能同时发生(推向两堵墙)。如果演员可以相交的两堵墙之间没有锐角(例如,如果您的所有障碍物都轴对齐且间隔足够),则依次修复每个碰撞就足够了 - 只是不要在第一次碰撞后停止。

【讨论】:

    【解决方案2】:

    你可以使用 Rectangle.intersects() 方法:

        public Rectangle Player(){
             return new Rectangle(PlayerX,PlayerY,PlayerWidth,PlayerHeight);
             //we do this for getting players x and y values every tick
        }
    
        if(Player().intersects(new Rectangle(0,0,100,50)))//if(player touching wall)
    

    new Rectangle(0,0,100,50) 只是一个示例,您可以更改它。

    【讨论】:

      【解决方案3】:

      好的,我目前正在制作一个 2D 俯视图游戏,但我不确定您是如何创建迷宫的。但是,在我的游戏中,我的关卡是从 Tile[][] tiles = new Tile[levelWidth][levelHeight]; 创建的。大批。我处理碰撞检测的方法是检查周围的瓷砖,看看它们是否是实心的。

      这是我的 getTile 方法。

      public Tile[][] getTile(int x, int y) {
          if (x < 0 || x >= getWidth() || y < 0 || y >= getHeight()) {
          return new VoidTile();
      } else {
          return tiles[x][y];
      }
      }
      

      在我的 Tile.java 类中,我有一个 isSolid() 方法,它返回瓷砖是否是实心的。我所有的图块都扩展了我的 Tile.java,所以它们继承了这个方法,我在它们的构造函数中重写了它。正如我之前所说,我不确定您是否使用与我相同的关卡实现方式。但是,这样做是个好习惯:)

      就我个人而言,我不太喜欢使用 .intersects() 和 .contains() 方法进行 Sprite 碰撞检测。我主要将它们用于按钮等。

      好的, 在我的 player.java 类中,我有一个 checkBlockedDirection(int x, int y) 方法,它看起来像这样。

          public void checkBlockedDirection(int x, int y) {
          boolean u = map.getTile(x, y - 1).isSolid();
          boolean d = map.getTile(x, y + 1).isSolid();
          boolean l = map.getTile(x - 1, y).isSolid();
          boolean r = map.getTile(x + 1, y).isSolid();
      
          if (u) {
              uBlocked = true;
              System.out.println("up tile blocked");
          } else {
              uBlocked = false;
          }
          if (d) {
              dBlocked = true;
              System.out.println("down tile blocked");
          } else {
              dBlocked = false;
          }
          if (l) {
              lBlocked = true;
              System.out.println("left tile blocked");
          } else {
              lBlocked = false;
          }
          if (r) {
              rBlocked = true;
              System.out.println("right tile blocked");
          } else {
              rBlocked = false;
          }
      }
      

      然后在我的播放器更新方法中我有这个

      public void tick() {
          float dx = 0;
          float dy = 0;
      
          if (input.up.isPressed()) {
              direction = 0;
          } else if (input.down.isPressed()) {
              direction = 2;
          } else if (input.left.isPressed()) {
              direction = 3;
          } else if (input.right.isPressed()) {
              direction = 1;
          } else {
              direction = 4; // standing
          }
      
          checkBlockedDirection((int)x, (int)y);
      
      
          if (input.up.isPressed() && y > 0 && !uBlocked) {
                  dy += -speed;
          } else if (input.down.isPressed() && y < map.getHeight() - 1 && !dBlocked) {
                  dy += speed;
          } else if (input.left.isPressed() && x > 0 && !lBlocked) {
                  dx += -speed;
          } else if (input.right.isPressed() && x < map.getWidth() - 1 && !rBlocked) {
                  dx += speed;
          }
          x += dx;
          y += dy;
      
      }
      

      基本上它只是检查上、下、左或右的块是否是实心的。如果它们是实心的,那么它不会移动,如果它们不是实心的,那么您可以朝所需的方向移动。

      不确定这是否有帮助,但这只是我对这种网格碰撞检测的看法:)

      希望这会有所帮助:)

      享受

      【讨论】:

        猜你喜欢
        • 2014-01-02
        • 1970-01-01
        • 2016-04-24
        • 1970-01-01
        • 1970-01-01
        • 2012-08-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多