2013-04-26 5 views
0

У меня очень плохое время здесь, чтобы найти ошибку в моем коде.C++ Прямоугольник прямоугольника Столкновение

Мое обнаружение столкновений здесь не будет работать даже в алгоритме, который я искал в Google.

void PollEvents() 
{ 

for (int i = 0;i < NUMBER_OF_BLOCKS; ++i) 
{ 

    Rectangle& a = blocks[i]; 

    if (mouse.state == GLFW_PRESS) 
    { 
     //look for any block to grab 
     if (mouse.leftClick && !blocks[selectedBlock].Grab() && 
      a.Hover(mouse.pos.x, mouse.pos.y)) 
     { 
      //prevent grabbing another block 
      if (i != selectedBlock) { 
       selectedBlock = i; 
      } 

      a.Grab() = true; 

      if (a.IsTypeHorizontal()) { 
       diff = mouse.pos.x - a.Left(); 
      } else { 
       diff = mouse.pos.y - a.Top(); 
      } 
     } 

     if (a.Grab()) 
     { 

      for (int j = 0;j < NUMBER_OF_BLOCKS; ++j) 
      { 
       //skip for any self-checking 
       if (i == j) continue; 

       Rectangle& b = blocks[j]; 

       //check for rectangle collision 
       if (!a.Collide(b) || b.Collide(a)) { 
        //j++; 
        //how does this block will move. 

        if (a.IsTypeVertical()) { 
         a.SetY(mouse.pos.y - diff); 
        } else { 
         a.SetX(mouse.pos.x - diff); 
        } 

       } else { 

        switch (a.sideHit) 
        { 
        case UP: 
         //a.SetY(b.Bottom()); 
         printf("UP\n"); 
         break; 
        case DOWN: 
         //a.SetY(b.Top() + a.GetHeight()); 
         printf("DOWN\n"); 
         break; 
        case LEFT: 
         //a.SetX(b.Right()); 
         printf("LEFT\n"); 
         break; 
        case RIGHT: 
         //a.SetX(b.Left() - a.GetWidth()); 
         printf("RIGHT\n"); 
         break; 
        } 
       } 

       //check for bound collision 
       a.BoundCheck(1.f); 
      } 

     } 

    } else { 
     a.Grab() = false; 
    } 
} 
} 

Обнаружение коллизий:

bool Rectangle::Collide(const Rectangle& r) { 

if (IsTypeHorizontal()) { 
    if (r.Hover(Left(), Top()) && r.Hover(Right(), Top())) { 
     sideHit = UP; 
     return true; 
    } else if (r.Hover(Right(), Bottom()) && r.Hover(Left(), Bottom())) { 
     sideHit = DOWN; 
     return true; 
    } 
    // } else if (r.Hover(Left(), Top())) { 
     // sideHit = UP; 
     // return true; 
    // } else if (r.Hover(Right(), Top())) { 
     // sideHit = UP; 
     // return true; 
    // } else if (r.Hover(Right(), Bottom())) { 
     // sideHit = DOWN; 
     // return true; 
    // } else if (r.Hover(Left(), Bottom())) { 
     // sideHit = DOWN; 
     // return true; 
    // } 
} else { 
    if (r.Hover(Left(), Top()) && r.Hover(Left(), Bottom())) { 
     sideHit = LEFT; 
     return true; 
    } else if (r.Hover(Right(), Top()) && r.Hover(Right(), Bottom())) { 
     sideHit = RIGHT; 
     return true; 
    } 
    // } else if (r.Hover(Left(), Top())) { 
     // sideHit = LEFT; 
     // return true; 
    // } else if (r.Hover(Left(), Bottom())) { 
     // sideHit = LEFT; 
     // return true; 
    // } else if (r.Hover(Right(), Top())) { 
     // sideHit = RIGHT; 
     // return true; 
    // } else if (r.Hover(Right(), Bottom())) { 
     // sideHit = RIGHT; 
     // return true; 
    // } 
} 

return false; 

} 

Код для Hover:

inline float Hover(float X, float Y) const { 
    return X >= Left() && 
      X <= Right() && 
      Y >= Bottom() && 
      Y <= Top(); 
} 

Я пытаюсь сделать мой собственный unblockme.

Пожалуйста, помогите мне в обнаружении столкновения. Прошло уже три дня с тех пор, как я застрял в этой проблеме.

UPDATE

я обнаружил проблему, почему все обнаружение столкновения Прямоугольник-Прямоугольник не будет работать в моей программе.

Ошибка:

if (!a.Collide(b)) { 

    //Move() 

} else { 

    //Resolve collision 
} 

Это один должен быть

if (!Rectangle::Collide(a, b)) { 

    //Move() 

} else { 

    //Resolve collision 

} 

Создание Collide() в static член Rectangle, потому что, как вы можете видеть в моей реализации Collide(), он основывает свое решение на своем собственном члене, так что a.Hover(b.x, b.y) не имеет никакого смысла.

Надеюсь, это поможет немногим новичкам, как я.

ответ

3

Чтобы выполнить обнаружение столкновения прямой/прямой, если какой-либо один (ребра, параллельные оси х и у), четыре точки прямоугольника находятся внутри другого прямоугольника, у нас есть столкновение.

Более простой способ проверить каждую из четырех точек - проверить, находится ли одно X-кратное расстояние между двумя ребрами другого ребра, и если один край Y находится между двумя ребрами Y-ребра - если оба они истинны, у нас есть столкновение (потому что два ребра должны встречаться в точке внутри другого прямоугольника). Таким образом, мы просто проверить это в обоих направлениях:

bool isclamped(float mid, float A, float B) 
{ 
    if (A > B) 
    { 
     return mid >= B && mid <= A; 
    } 
    return mid >= A && mid <= B; 
} 

bool checkcollisiononeway(rect rectA, rect rectB) 
{ 
    if (isclamped(rectA.left, rectB.left, rectB.right) 
    || isclamped(rectA.right, rectB.left, rectB.right)) 
    && (isclamped(rectA.bottom, rectB.bottom, rectB.top) 
    || isclamped(rectA.top, rectB.bottom, rectB.top)) 
    { 
     return true; 
    } 
    return false; 
} 

bool checkcollisionbothways(rect rectA, rect rectB) 
{ 
    return checkcollisiononeway(rectA, rectB) || checkcollisiononeway(rectB, rectA); 
} 

Для определения угла столкновения после обнаружения столкновения, найти угол между двумя центрами, используя atan2(rectA.y - rectB.y, rectA.x - rectB.x) (угол возвращается в радианах, а не в градусах)

+0

Ухх..Это любопытный тупой вопрос, но базовый код, который я опубликовал, ж/с один - прямой и прямой? – mr5

+0

@ mr5 Один из прямоугольников в столкновении - rectA, другой - rectB. Они просто имена заполнителей. – Patashu

+0

Я имею в виду, это тот, который был 'a.Grab()' должен проверяться на столкновение? – mr5