2012-04-23 2 views
3

Я занимаюсь программированием для класса. Мы программируем игру, которая состоит из мяча, весла, четырех краев и кирпичей. мяч отскакивает от разных объектов, и каждый объект выполняет различные операции над собой при обнаружении столкновения. ниже мой код, который в настоящее время не работает. Я пытаюсь использовать расположение объекта (его центральную точку), чтобы построить ограниченную рамку и значения каждого края (верхний, нижний, левый, правый), чтобы вычислить, попали ли ящики. Я подумал, что могут быть два типа столкновений, где ударяются углы, и где один объект попадает где-то посередине другого объекта. Пожалуйста, просмотрите мой код и помогите, если сможете. Я не знаю, есть ли лучший способ сделать то, что я пытаюсь сделать, но то, что у меня в настоящее время не работает, и возвращает значение true почти все время.Обнаружение столкновений с использованием ограниченных полей

Это часть кода, которая проверяет каждый объект, который может сталкиваться с любым другим объектом, который может столкнуться. он также перемещает каждый объект и помечает часы игры.

/** 
    * 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 поэтапно, часто более эффективным для проверки «рыхлой возможности», что некоторые объекты могут столкнуться, то проверить, могли ли они, затем проверить окончательно. Это связано с тем, что большую часть времени ваши объекты не будут нигде не сталкиваться. Вы могли бы добавить код к своему ответу, который проверяет, находится ли шар в области (например, нижняя половина экрана, минус область лопастей и стороны), где не может быть столкновения, и короткое замыкание на этом. –

+1

Рассматривали ли вы использование Java 2D API? Вы получите готовый [Rectangle class] (http://docs.oracle.com/javase/1.5.0/docs/api/java/awt/Rectangle.html) с готовыми пересечениями (Rectangle) метод. :) – ZeroOne

+1

См. Также Переполнение стека: [Определение, перекрываются ли два прямоугольника друг с другом] (http://stackoverflow.com/questions/306316/determine-if-two-rectangles-overlap-each-other)? – ZeroOne

ответ

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 для какого-либо объекта. Когда она сравнивается с каждым объектом в игре World, даже когда объект (мяч) находится посередине экрана, ничего не касаясь.Если вы рисуете два квадрата непосредственно рядом друг с другом, но не касаетесь, то r1 будет меньше l2, что неверно, поэтому в моем первоначальном примере, который я разместил, я попытался сравнить все соответствующие стороны, но это тоже не сработало. –

+0

Извинения, которые, как я полагал, я пропустил, набрав его. Возврат должен быть обратным: /. Я отредактировал ответ. – rflood89

+0

Вам удалось получить эту работу еще? – rflood89

Смежные вопросы