2011-10-16 191 views
0

可能重複:
Java 2D Collision?的Java 2D碰撞

嗨我有一個關於這個另一篇文章剛剛死了,所以我想我會嘗試得到這方面的一些新答案。

我試圖讓我的碰撞檢測工作。碰撞檢測工作正常,當我走到地圖塊的旁邊時,罰款時我只能保持或停止並從頂部或底部打一個塊。但是當我站起來或者站在右邊或者左邊,並且從頂部或者底部碰到一個障礙物時,它會沿着有趣的方向走下去。

小視頻我演示(對不起,如果不清楚):http://www.youtube.com/watch?v=6ILccRtw8ME希望這可以幫助很多。

如果你沒看這裏的視頻的畫面地圖的我會用:

enter image description here

這是我目前的碰撞代碼:

public void checkCollision() { 
    Rectangle player_rectangle = new Rectangle(player.getX(),player.getY(),32,32); 

    for(Wall wall : walls) { 

     Rectangle wall_rectangle = new Rectangle(wall.getX(), wall.getY(), 32,32); 

     if (player_rectangle.intersects(wall_rectangle)) { 
      Rectangle intersection = (Rectangle) player_rectangle.createIntersection(wall_rectangle); 


      if (player.xspeed < 0 && player.x >= intersection.x) { 
       player.x += intersection.getWidth(); 
      } else { 

      if (player.xspeed > 0 && player.x <= intersection.x) { 
       player.x -= intersection.getWidth(); 
      } else { 

      if (player.yspeed < 0 && player.y >= intersection.y) { 
       player.y += intersection.getHeight(); 
      }else { 

      if (player.yspeed > 0 && player.y <= intersection.y) { 
       player.y -= intersection.getHeight(); 
      } 
      } 
      } 
      } 



      Print(Integer.toString(intersection.width) + ", " + Integer.toString(intersection.height)); 

     } 

    } 

} 

所有幫助將不勝感激,謝謝。

+0

是不是你問你的[舊的文章]同樣的問題(http://stackoverflow.com/questions/7763244/java-2d-collision)?如果是,請編輯和/或開始賞金最後一個問題,不要重新發布。如果不是,請詳細解釋問題。 – amit

+0

爲有趣的視頻+1。塊扭曲ftw。 –

+0

@ThomasJungblut你是什麼意思? :L –

回答

3

這是我第一次嘗試回答StackOverflow的問題,請耐心等待。我將嘗試通過首先診斷問題,找出可能導致您的問題的症狀並最後提出解決方案並查看它是否適用於您,來構建此答案。

首先,讓我用正確的縮進級別對代碼進行格式化,以便我們對發生的事情有更清晰的瞭解。

public void checkCollision() { 
    Rectangle player_rectangle = new Rectangle(player.getX(), 
      player.getY(), 32, 32); 

    for (Wall wall : walls) { 

     Rectangle wall_rectangle = new Rectangle(wall.getX(), wall.getY(), 
       32, 32); 

     if (player_rectangle.intersects(wall_rectangle)) { 
      Rectangle intersection = (Rectangle) player_rectangle 
        .createIntersection(wall_rectangle); 

      if (player.xspeed < 0 && player.x >= intersection.x) { 
       player.x += intersection.getWidth(); 
      } else { 

       if (player.xspeed > 0 && player.x <= intersection.x) { 
        player.x -= intersection.getWidth(); 
       } else { 

        if (player.yspeed < 0 && player.y >= intersection.y) { 
         player.y += intersection.getHeight(); 
        } else { 

         if (player.yspeed > 0 && player.y <= intersection.y) { 
          player.y -= intersection.getHeight(); 
         } 
        } 
       } 
      } 

      Print(Integer.toString(intersection.width) + ", " 
        + Integer.toString(intersection.height)); 

     } 

    } 

} 

既然我們已經完成了這一步,那麼您就越清楚自己在做什麼。我注意到的第一件事是你在嵌套你的條件語句。爲了澄清,你這樣做:

if (condition){ 
    // do something 
    else{ 
     if(anotherCondition){ 
      // do something 
      else{ 
       //etc 
      } 
     } 
    } 
} 

你應該使用多個條件語句連續這樣做:

if (condition){ 
    //do something 
} 

if (anotherCondition){ 
    //do something else 
} 

//etc 

這是因爲如果你有兩個情況,比如你在左下角,您需要執行交叉點左側和交叉點的條件。但是,由於您單獨穿過每個牆,因此這與您的示例無關。

那麼爲什麼這很重要?

那麼,在我看來,如果第一個條件不滿足,那麼所有其他條件將不會執行。如果player.xspeed < 0 && player.x >= intersection.x返回true,那麼即使其中嵌套的其他3個語句返回true,它們也不會被執行,因爲它依賴於第一個語句爲false。因此,當你走到邊緣時,兩個或兩個以上的情況是正確的,你只能得到其中一個被執行。

因此,我提出的解決方案,基於上述所有是這樣的:

public void checkCollision() { 
     Rectangle player_rectangle = new Rectangle(player.getX(), 
       player.getY(), 32, 32); 

     for (Wall wall : walls) { 

      Rectangle wall_rectangle = new Rectangle(wall.getX(), wall.getY(), 
        32, 32); 

      if (player_rectangle.intersects(wall_rectangle)) { 
       Rectangle intersection = (Rectangle) player_rectangle 
         .createIntersection(wall_rectangle); 

       if (player.xspeed < 0 && player.x >= intersection.x) { 
        player.x += intersection.getWidth(); 
       } 

       if (player.xspeed > 0 && player.x <= intersection.x) { 
        player.x -= intersection.getWidth(); 
       } 

       if (player.yspeed < 0 && player.y >= intersection.y) { 
        player.y += intersection.getHeight(); 
       } 

       if (player.yspeed > 0 && player.y <= intersection.y) { 
        player.y -= intersection.getHeight(); 
       } 

       Print(Integer.toString(intersection.width) + ", " 
         + Integer.toString(intersection.height)); 

      } 

     } 

    } 

試試這個,看看它是否工作。如果沒有,那麼我們可以從那裏拿走它,看看如何改進和解決你的問題。

+0

感謝您的回覆,遺憾的是現在不能使用該代碼:L即使從右側或左側進入並保持向上/向下,它也會隨機跳轉 –

+0

有趣。我可能需要儘快編輯我的答案。需要進一步思考。 – CodingMo

0

我建議爲所有不同的狀態編寫一堆單元測試,你可以想象checkCollision需要處理。 這樣,你會:

  • 輕鬆找出哪些特定的輸入導致塊跳躍(因爲單元測試是短,以及包含的)
  • 確保此功能將不會被打破的未來變化(因爲單元測試與每個版本上運行)

這樣做的一個抽樣單元測試會是這個樣子:

public class CollisionTests { 

    @Test 
    public void hitFromLeftHeadOn() throws Exception { 
     List<Wall> walls = Lists.newArrayList(
      new Wall(...), // south wall 
      new Wall(...), // east wall 
      // etc. 
     ); 
     Player player = new Player(...); 

     // Set player to collide with the east wall head on 
     player.setX(...); 
     player.setY(...); 
     player.setXSpeed(...); 
     player.setYSpeed(...); 

     checkCollision(); 

     // Now check if the checkCollision method worked properly 
     assertEquals("Player's x coordinate should be set to ...", ..., player.getX()); 
     assertEquals("Player's y coordinate should be set to ...", ..., player.getY()); 
    } 

一旦你寫了一個測試,很容易添加更多。您可以創建各種幫助器方法來創建牆壁,播放器等,以便每個測試案例縮小到幾行。

Here's a tutorial on unit testing.

作爲額外的獎勵,如果你寫一個單元測試,你會還寫了SSCCE :)