Breakout Collision: Wykrywanie strony kolizji

10

Piszę breakout clone (moja pierwsza gra) i całkowicie utknąłem w tym, jak dowiedzieć się, która strona klocka została trafiona.

Mam metodę wykrywania kolizji, która wygląda następująco:

DetectCollision(Object a, Object b)

   x = distance(a.x, b.x);
   y = distance(a.y, b.y);

   if (x is smaller than the combined width &  y is smaller is than combined height {
       return true;
   }
return false;  

Działa to całkowicie dobrze, ale muszę znać stronę kolizji i lokalizację względem środka, aby odpowiednio zareagować.

Spędziłem ostatnie kilka dni węsząc dookoła, ale jestem zagubiony.

użytkownik590903
źródło

Odpowiedzi:

13

Wszystko to można uzyskać na podstawie położenia kulki względem położenia zderzanej cegły.

Po wykryciu kolizji:

if(ballPosition.y <= brickPosition.y - (brickHeight/2))
  //Hit was from below the brick

if(ballPosition.y >= brickPosition.y + (brickHeight/2))
  //Hit was from above the brick

if(ballPostion.x < brickPosition.x)
  //Hit was on left

if(ballPostion.x > brickPosition.x)
  //Hit was on right

Pierwsze dwa sprawdzają, czy piłka znajduje się nad, czy pod cegłą. Jeśli żadne z nich nie musi znajdować się obok klocka, sprawdź więc, po której stronie jest. Trzeba będzie go dostosować, aby zmieścił się w miejscu, z którego bierzesz lokalizację, tj. BrickPosition jest środkiem cegły lub brickPosition jest lewym górnym rogiem.

MichaelHouse
źródło
1
Ale w jaki sposób użyjesz tego do zmiany położenia gracza, ponieważ gracz porusza się wewnątrz cegły, spełni się wiele z tych warunków, a jeśli zresetujesz żądany x do krawędzi ściany, na przykład, jeśli uderzy on w klucz klocka ustaw żądany x dokładnie przy ścianie, to tak naprawdę nie zadziałałoby, ponieważ gdy sprawdzasz teoretyczną pozycję postaci, aby zobaczyć, w którym kierunku się zderza, spełniony zostanie wiele z tych warunków, więc jak byś to zrobił użyj tego, aby zresetować odtwarzacz, czy musisz dodawać inne na końcu każdego jeśli)?
bluejayke
O ile mi wiadomo, „graczem” w grze typu breakout jest wiosło. Wiosło nie porusza się wewnątrz klocka, ani nie zmienia się położenia wiosła w oparciu o interakcję piłki z cegłami. Jeśli to właśnie robisz, nie potrzebujesz dodatkowej logiki, po prostu nie przetwarzaj repozycji, dopóki nie wykonasz wszystkich kontroli kolizji. Lub wróć, gdy jedna z kontroli będzie prawdziwa.
MichaelHouse
8

Możesz użyć Vector Math, aby odkryć kąty między nimi!

Oto krótka odpowiedź:

ballToBrick = ballPosition - brickPosition;
ballToBrick.Normalize();
brickFacing = Vector2(0,1).Normalize();


float angle = acos( Dot(ballToBrick, brickFacing) );

Cegła licowa jest trudnym wektorem, jest „punktem początkowym” obliczenia kąta. a jeśli chcesz, aby wektor wskazywał w górę, ustaw go (0, 1), wskaż w lewo (-1, 0), w prawo (1, 0), wskaż w dół (0, -1). Zakładając, że jesteś w osi OpenGL, gdzie góra i prawo są dodatnie.

Jeśli nie wiesz, oto definicje każdej użytej funkcji:

Vector2.Normalize()
{
    float length = squareroot(x * x + y * y);
    x = x / length;
    y = y / length;
    return this;
}

Dot(Vector2 a, Vector2 b)
{
    return a.x * b.x + a.y * b.y;
}

( https://en.wikipedia.org/wiki/Dot_product )

Odniesienie: http://blog.wolfire.com/2009/07/linear-algebra-for-game-developers-part-2/

Gustavo Maciel
źródło