2012-04-23 39 views
3

我正在爲類進行編程項目。我們正在編寫遊戲突破,其中包括一個球,一個槳,四個邊和磚。當碰撞被檢測到時,球從不同的物體反彈並且每個物體對其本身執行不同的操作。下面是我的代碼,目前不起作用。我試圖使用對象的位置(它的中心點)來構造一個有界框和每個邊的值(Top,Bottom,Left,Right)來計算這些框是否命中。我在腦海中想到,碰撞可能有兩種類型,一種是角落撞擊,另一種是一種物體撞擊另一種物體中間的某種物體。如果可以的話,請查看我的代碼並提供幫助。我不知道是否有更好的方法來做我想做的事情,但我目前沒有工作,並且幾乎總是返回真值。使用有界框進行碰撞檢測

這是代碼的一部分,用於檢查每個能夠與可能發生碰撞的其他對象碰撞的對象。它也會移動每個對象並打上游戲的時鐘。

/** 
    * Tell the GameWorld that the "game clock" has ticked. A clock tick in the GameWorld has the 
    * following effects: (1) all movable objects are told to update their positions according to there 
    * current heading and speed, (2) the "elapsed game time" is incremented by one and (3) all Items are 
    * checked for a collision. 
    */ 
    public void tickClock() { 
     gameClock++; 
     Iterator theElements0 = listOfGameObjects.getIterator(); 
     while (theElements0.hasNext()){ 
      GameObject gObj = (GameObject) theElements0.getNext(); 
      if (gObj instanceof IMovable){ 
       IMovable mObj = (IMovable)gObj; 
       mObj.move(gameClock); 
      } 
     } 
     Iterator theElements1 = listOfGameObjects.getIterator(); 
     while (theElements1.hasNext()){ 
      GameObject gObj0 = theElements1.getNext();//get a collidable object. 
      if(gObj0 instanceof ICollider){ 
       ICollider curObj = (ICollider) gObj0; 
       //check if this object collides with any OTHER object. 
       Iterator theElements2 = listOfGameObjects.getIterator(); 
       while(theElements2.hasNext()){ 
        GameObject gObj1 = theElements2.getNext(); 
        if(gObj1 != curObj && gObj1 instanceof ICollider) { 
         ICollider otherObj = (ICollider) gObj1; 
         if (curObj.collidesWith(otherObj)){ 
          curObj.handleCollision(otherObj); 
         } 
        } 
       } 
      } 
     } 
     setChanged(); 
     notifyObservers(); 
    } 

這是用於確定對象是否與另一對象發生碰撞,並且還適當的行動採取如果它具有的代碼的一部分。這段代碼特別來自球對象,所以當它碰到磚時執行的動作是ySpeed被顛倒過來。

public boolean collidesWith(ICollider otherObj) { 
     GameObject gObj = (GameObject) otherObj; 
     //this collider 
     int r1 = (int) (getX() + getWidth()/2); 
     int l1 = (int) (getX() - getWidth()/2); 
     int t1 = (int) (getY() + getHeight()/2); 
     int b1 = (int) (getY() - getHeight()/2); 

     //the other collider 
     int r2 = (int) (gObj.getX() + gObj.getWidth()/2); 
     int l2 = (int) (gObj.getX() - gObj.getWidth()/2); 
     int t2 = (int) (gObj.getY() + gObj.getHeight()/2); 
     int b2 = (int) (gObj.getY() - gObj.getHeight()/2); 

     //corner collision check 
     if(r1>l2 && t2>b1 && t1>t2 && b1>b2){ 
      System.out.println("Corner Collision check 1"); 
      return true; 
     } 
     if(r2>l1 && t2>b1 && t1>t2 && b1>b2){ 
      System.out.println("Corner Collision check 2"); 
      return true; 
     } 
     if(r2>l1 && t1>b2 && t2>t1 && b2>b1){ 
      System.out.println("Corner Collision check 3"); 
      return true; 
     } 
     if(r1>l2 && t1>b2 && t2>t1 && b2>b1){ 
      System.out.println("Corner Collision check 4"); 
      return true; 
     } 

     //middle collision check 
     if(l1>l2 && r1<r2 && t1<t2 && b1<b2){ 
      System.out.println("middle collision check 1"); 
      return true; 
     } 
     if(l1>l2 && r1<r2 && t1>t2 && b1>b2){ 
      System.out.println("middle Collision check 2"); 
      return true; 
     } 
     if(l1<l2 && r1<r2 && t1<t2 && b1>b2){ 
      System.out.println("middle Collision check 3"); 
      return true; 
     } 
     if(l1>l2 && r1>r2 && t1<t2 && b1>b2){ 
      return true; 
     } 

     return false; 
    } 

    public void handleCollision(ICollider otherObject) { 
     if(otherObject instanceof Brick){ 
      System.out.println("Brick Hit"); 
      ySpeed = -(ySpeed); 
     } 
    } 
+0

此外,請記住您可以檢查階段collsions,它往往是更有效的檢查了「寬鬆的可能性」,一些對象可能發生碰撞,然後檢查他們是否可以,然後檢查明確。這是因爲大多數時候,你的物體不會接近碰撞。您可以在答案中添加代碼,檢查球是否位於不可能發生碰撞的區域(例如屏幕的下半部分,減去槳區和側面),以及短路情況。 – 2012-04-24 00:18:42

+1

你有沒有考慮過使用Java 2D API?您將獲得一個現成的[Rectangle類](http://docs.oracle.com/javase/1.5.0/docs/api/java/awt/Rectangle.html),其中包含一個現成的相交(Rectangle)方法。 :) – ZeroOne 2012-04-24 08:54:55

+1

另請參見堆棧溢出:[確定如果兩個矩形相互重疊](http://stackoverflow.com/questions/306316/determine-if-two-rectangles-overlap-each-other)? – ZeroOne 2012-04-24 09:00:40

回答

8

你只需要檢查邊邊框。一些僞代碼可能看起來像。

if Rect1[RIGHT] < Rect2[LEFT] or 
    Rect1[LEFT] > Rect2[RIGHT] or 
    Rect1[TOP] < Rect2[BOTTOM] or 
    Rect1[BOTTOM] > Rect2[TOP] 
then return false 
else return true 

這是什麼想說的是,如果有沿X或Y的任何可能的差距座標系統分離的框,然後碰撞是不可能的。這是一個非常簡單版本的SAT (Separating Axis Theorem)

這是一個什麼樣的視覺像一個小圖像,這裏同樣的想法也適用。

Visualisation of SAT

這應該意味着類似於下面的東西應該工作。請注意,我沒有測試它,但可能導致您朝着正確的方向前進。

public boolean collidesWith(ICollider otherObj) { 
    GameObject gObj = (GameObject) otherObj; 
    //this collider 
    int r1 = (int) (getX() + getWidth()/2); 
    int l1 = (int) (getX() - getWidth()/2); 
    int t1 = (int) (getY() + getHeight()/2); 
    int b1 = (int) (getY() - getHeight()/2); 

    //the other collider 
    int r2 = (int) (gObj.getX() + gObj.getWidth()/2); 
    int l2 = (int) (gObj.getX() - gObj.getWidth()/2); 
    int t2 = (int) (gObj.getY() + gObj.getHeight()/2); 
    int b2 = (int) (gObj.getY() - gObj.getHeight()/2); 

    if (r1 < l2 || l1 > r2 || t1 < b2 || b1 > t2) 
     return false; 
    else 
     return true; 

    /* Or could be shortened down to 
    return !(r1 < l2 || l1 > r2 || t1 < b2 || b1 > t2) */ 

} 

代碼不會你說的相當的下降;)

+0

我以前已經嘗試過。問題是這個操作對於某個對象總是返回true當它與gameWorld中的每個對象進行比較時,即使對象(球)在屏幕中間什麼也不碰。如果你直接相鄰的兩個方格但不碰觸,那麼r1將小於l2,這是不正確的,所以在我發佈的原始示例中,我試着比較所有相應的邊,但那也不起作用。 – 2012-04-24 00:31:19

+0

我相信我錯過打字的道歉。回報應該是相反的:/。我編輯了答案。 – rflood89 2012-04-24 20:54:41

+0

你是否設法讓這個工作呢? – rflood89 2012-04-25 16:38:16