Witam :>.
Wczoraj pisałem, że poprawiłem trochę funkcje kolizji. Natomiast wieczorem w łóżku wpadłem na jeszcze lepszy pomysł, który uprości mi pracę :). Postaram się przybliżyć Wam moją metodę, być może ktoś skorzysta.
Metoda, którą ja stosuje doskonale sprawdza się w grach 2D, gdzie postacie są określone jako kwadraty nałożone teksturą.
Zanim jednak przedstawię Wam moją funkcję, musimy zbudować typ wyliczeniowy. Oto on:
enum Kierunek
{
V_LEFT,
V_RIGHT,
V_UP,
V_DOWN
};
Co on określa? Określa kierunek, w jakim porusza się lub, lepiej, MA się poruszać dana postać. Tworzymy więc jeden taki typ:
Kierunek tKolizja;
Teraz potrzebujemy jeszcze struktury postaci. Dla naszego przykładu wystarczy taka zawierająca tylko współrzedne tekstury. Współrzędne to 8 elementów (X, Y). Po jednym na każdy bok kwadratu:
struct Character
{
GLfloat WspX1; // wspolrzedna gorna prawa
GLfloat WspX2; // wspolrzedna gorna lewa
GLfloat WspX3; // wspolrzedna dolna lewa
GLfloat WspX4; // wspolrzedna dolna prawa
GLfloat WspY1; // wspolrzedna gorna prawa
GLfloat WspY2; // wspolrzedna gorna lewa
GLfloat WspY3; // wspolrzedna dolna lewa
GLfloat WspY4; // wspolrzedna dolna prawa
};
Typ GLfloat to OpenGL’owska liczba zmiennoprzecinkowa.
Teraz możemy stworzyć naszą funkcję glCollisions():
bool glCollisions(Character Pierwszy, Character Drugi, Kierunek tKierunek)
Jak widać przyjmuje ona 3 wartości: “Pierwszy” to postać, która ma się poruszać w kierunku określonym w tKierunek, a my sprawdzamy, czy jest to możliwe. “Drugi” natomiast, to postać, którą sprawdzamy, czy nie stoi czasem na przeszkodzie postaci pierwszej - nie chcemy przecież, aby przez siebie przechodziły. Funkcja zwraca wartość bool - true, jeśli doszło do kolizji lub false, jeśli nic nie stoi postaci na przeszkodzie. I teraz zanim przejde do bloku funkcji, chcę uprzedzić, że można to było zrobić za pomocą np. instrukcji switch() i być może tak byłoby nawet wydajniej :>>. Ja zrobiłem na if’ach, proszę mnie za to nie bić ;P
Cała funkcja wygląda u mnie tak:
bool glCollisions2(Character Pierwszy, Character Drugi, Kierunek tKierunek)
{
if(tKierunek == V_LEFT)
{
if((Pierwszy.WspX2 >= Drugi.WspX1) && (Drugi.WspX1 >= Pierwszy.WspX2 - 0.02f) && (Drugi.WspY3 <= Pierwszy.WspY1) && (Pierwszy.WspY3 <= Drugi.WspY1))
return true;
}
else if(tKierunek == V_RIGHT)
{
if((Drugi.WspX2 >= Pierwszy.WspX1) && (Pierwszy.WspX1 >= Drugi.WspX2 - 0.02f) && (Pierwszy.WspY3 <= Drugi.WspY1) && (Drugi.WspY3 <= Pierwszy.WspY1))
return true;
}
else if(tKierunek == V_UP)
{
if((Drugi.WspY3 >= Pierwszy.WspY1) && (Pierwszy.WspY1 >= Drugi.WspY3 - 0.02f) && (Pierwszy.WspX2 <= Drugi.WspX1) && (Drugi.WspX2 <= Pierwszy.WspX1))
return true;
}
else if(tKierunek == V_DOWN)
{
if((Pierwszy.WspY3 >= Drugi.WspY1) && (Drugi.WspY1 >= Pierwszy.WspY3 - 0.02f) && (Drugi.WspX2 <= Pierwszy.WspX1) && (Pierwszy.WspX2 <= Drugi.WspX1))
return true;
}
return false;
}
Omówię teraz jeden blok kiedy tKierunek ma wartość V_LEFT. Myślę, że resztę już zrozumiecie sami na podstawie tego jednego przykładu. Ja zajmę się wyjaśnieniem tylko ponizszego bloku kodu:
if((Pierwszy.WspX2 >= Drugi.WspX1) && (Drugi.WspX1 >= Pierwszy.WspX2 - 0.02f) && (Drugi.WspY3 <= Pierwszy.WspY1) && (Pierwszy.WspY3 <= Drugi.WspY1))
A więc: obiekt “Pierwszy” chcemy przesunąć w lewo, ale być może obiekt “Drugi” stoi mu na drodze - i to chcemy w tym kodzie sprawdzić. W pierwszym nawiasie sprawdzamy, czy lewa górna współrzedna obiektu pierwszego jest wieksza badz równa prawej gornej współrzednej obiektu drugiego. W drugim natomiast sprawdzamy, czy prawa gorna wspolrzedna obiektu drugiego jest wieksza badz rowna lewej gornej wspolrzednej obiektu pierwszego, jesli odejmiemy od niej wartosc 0.02. 0.02 dlatego, iż tyle wynosi u mnie jeden ruch po wcisnieciu np. strzałki. Sprawdzamy więc, czy obiekt nie jest za wysoko względem Drugiego.
Trzeci i czwarty nawias to w zasadzie analogia dwoch poprzednich.
I to by było na tyle. Mam nadzieję, że komuś się to przyda ;>
pozdrawiam,
M.