Код столкновения коробки - PullRequest
0 голосов
/ 21 мая 2011

Код столкновения моего ящика не работает.

bool checkCollide(int x, int y, int oWidth, int oHeight, int xTwo, int yTwo, int oTwoWidth, int oTwoHeight)
{
   if (xTwo + oTwoWidth < x) 
      return false;  // box 2 is left of box 1

   if (x + oWidth < xTwo)
      return false;  // box 1 is left of box 2

   if (xTwo > x + oWidth) 
      return false;  // box 2 is right of box 1

   if (x > xTwo + oTwoWidth)
      return false;  // box 1 is right of box 2


   if (yTwo + oTwoHeight < y) 
      return false;  // box 2 is up of box 1

   if (y + oHeight < yTwo)
      return false;  // box 1 is up of box 2

   if (yTwo > y + oHeight) 
      return false;  // box 2 is down of box 1

   if (y > yTwo + oTwoHeight)
      return false;  // box 1 is down of box 2

   return true;
}

Один из моих ящиков явно пересекает другой, однако ничего не происходит.Кажется, по какой-то причине возвращается false.Я проверяю, находится ли один «прямоугольник» за пределами другого, и не возвращает ли он true.Почему не работает?

Ответы [ 2 ]

10 голосов
/ 21 мая 2011

Вот как я бы это сделал (я бы предоставил объект AABB вместо корыта)

bool checkCollide(int x, int y, int oWidth, int oHeight, int xTwo, int yTwo, int oTwoWidth, int oTwoHeight)
{
    // AABB 1
    int x1Min = x;
    int x1Max = x+oWidth;
    int y1Max = y+oHeight;
    int y1Min = y;

    // AABB 2
    int x2Min = xTwo;
    int x2Max = xTwo+oTwoWidth;
    int y2Max = yTwo+oTwoHeight;
    int y2Min = yTwo;

    // Collision tests
    if( x1Max < x2Min || x1Min > x2Max ) return false;
    if( y1Max < y2Min || y1Min > y2Max ) return false;

    return true;
}

Действительно, вы можете напрямую заменить x1Max и т. Д. На значения вместо использования временных переменных.Я добавил их для удобства чтения.

bool checkCollide(int x, int y, int oWidth, int oHeight, int xTwo, int yTwo, int oTwoWidth, int oTwoHeight)
{
    if( x+oWidth < xTwo || x > xTwo+oTwoWidth ) return false;
    if( y+oHeight < yTwo || y > yTwo+oTwoHeight ) return false;

    return true;
}

Обратите внимание, что эта функция работает только с 2D-блоками, но для 3D-совместимости требуется только еще одна тестовая линия с осью z.

----------

Теперь давайте посмотрим ваш код с некоторыми комментариями к нему

bool checkCollide(int x, int y, int oWidth, int oHeight, int xTwo, int yTwo, int oTwoWidth, int oTwoHeight)
{
   if (xTwo + oTwoWidth < x)    //(1) if( x2Max < x1Min )
      return false;

   if (x + oWidth < xTwo)       //(2) if( x1Max < x2Min )
      return false;

   if (xTwo > x + oWidth)       //(3) if( x2Min > x1Max ) ==> if( x1Max < x2Min ) ==> (2)
      return false;

   if (x > xTwo + oTwoWidth)    //(4) if( x1Min > x2Max ) ==> if( x2Max < x1Min ) ==> (1)
      return false; 


   if (yTwo + oTwoHeight < y)   //(5) if( y2Max < y1Min )
      return false;

   if (y + oHeight < yTwo)      //(6) if( y1Max < y2Min )
      return false;

   if (yTwo > y + oHeight)      //(7) if( y2Min > y1Max ) ==> if( y1Max < y2Min ) ==> (6)
      return false;

   if (y > yTwo + oTwoHeight)   //(8) if( y1Min > y2Max ) ==> if( y2Max < y1Min ) ==> (5)
      return false;

   return true;
}

Итак, как вы можете видеть, половина тестовне требуются.Учитывая ось X, ваш первый тест такой же, как и четвертый;Ваш второй тест такой же, как и третий.

----------

Однако я не могу определить причину, по которой ваша функция не возвращает true, когдакоробка перекрывается.Это должно работать.

Я протестировал со следующими значениями

std::cout << checkCollide(5, 5, 2, 2, 0, 0, 3, 3) << std::endl; // false no collision
std::cout << checkCollide(5, 5, 2, 2, 4, 4, 3, 3) << std::endl; // true collision

И он возвращает false и true, как и ожидалось.

0 голосов
/ 21 мая 2011
bool checkCollide(int x1, int y1, int w1, int h1, int x2, int y2, int w2, int h2) {
  if (y1 + h1 < y2
     || y1 > y2 + h2
     || x1 + w1 < x2
     || x1 > x2 + w2) return false;
  return true;
}
...