Autor Wątek: [C++] Detekcja kolizji bounding box zrobiona, tylko co ze stroną bbx'a ?  (Przeczytany 1578 razy)

Offline JasonVoorhees

  • Użytkownik
    • FotoGry

# Lipiec 07, 2007, 13:35:31
Witam.
Tak wgląda moja detekcja kolizji, potrzebuję tylko kolizję gracza z otoczeniem (nie potrzebuję osi Y, bo postać się po niej nie porusza):
void CMap::CollisionDetectionWith(bbx BBX)
{
    Points[0][0]=bbx_hand[0]+Px;
    Points[0][1]=bbx_hand[2]+Pz;

    Points[1][0]=bbx_hand[0]+Px;
    Points[1][1]=bbx_hand[3]+Pz;

    Points[2][0]=bbx_hand[1]+Px;
    Points[2][1]=bbx_hand[2]+Pz;

    Points[3][0]=bbx_hand[1]+Px;
    Points[3][1]=bbx_hand[3]+Pz;
    point sciana={0,0};
    for (int i=0;i<=3;i++)
    {
        if (OnCollision(Points[i],BBX))
        {
            CZ=CZ2=CX=CX2=false; // blokujemy przemieszczanie się we wszystkich kierunkach
        }
    }
}

bool CMap::OnCollision(point Point,bbx Quad)
{
if(Quad[0] >= Point[0]) return false;
if(Quad[1] <= Point[0]) return false;
if(Quad[2] >= Point[1]) return false;
if(Quad[3] <= Point[1]) return false;
return true;
}


void CMap::CollisionDetection()
{
CollisionDetectionWith(bbx_house);
}
To działa tak, że jak następuje kolizja, postać nie może się poruszyć (i to działa dobrze :) ), tak wygląda przemieszczanie się postacią (na razie tylko próbuję na poruszaniu się do przodu):
void player::moveForward(float angle)
{
    float X=sin(angle)*0.25;
    if ((cx)&&(X<0) || (cx2)&&(X>0)) position.x+=X;
    float Z=cos(angle)*0.25;
    if ((cz)&&(Z<0) || (cz2)&&(Z>0)) position.z+=Z;
}
I teraz pytanie, jak dopisać do tego kodu, żeby jak postać zderzy się ze ścianą obiektu to żeby nie mogła iść dalej do przodu i poruszała się tylko po osi x ?? itd. dla każdej ściany... Jak to zrobić najlepiej :) ?? Takie zderzenie ze ścianą jest w wielu grach, nawet w starym Duke Nukem 3D tak jest, i chyba nawet trochę gorzej w Wolf 3D...

Z góry dzięki za odpowiedzi :)

Offline Mr. Spam

  • Miłośnik przetworów mięsnych

Offline Krzysiek K.

  • Redaktor
    • DevKK.net

# Lipiec 07, 2007, 14:01:58
Dane wejściowe:
(xp,yp) - pozycja gracza
(dx,dy) - przesunięcie gracza

Algorytm
1. Zapamiętaj stare położenie ox=xp, oy=yp,
2. Przesyń gracza w osi X: xp+=dx,
3. Jeżeli wystąpiła kolizja, przywróć stare położenie X: xp=ox,
4. Przesuń gracza w osi Y: yp+=dy,
5. Jeżeli wystąpiła kolizja, przywróć stare położenie Y: yp=oy,

Co prawda trzeba sprawdzac kolizję dwukrotnie, ale gracz będzie się poprawnie "ślizgał" po poziomych i pionowych ścianach (ale takie proste podejście nie zadziała juz dla ścian ukośnych). :)

Offline Moriturius

  • Użytkownik

# Lipiec 07, 2007, 14:32:55
Najlepiej to wykrywać kolizje za pomocą mechanizmu SAT który Spider świetnie opisał tutaj: http://forum.warsztat.gd/index.php/topic,1913.msg25544.html#msg25544

A ja właśnie skończyłem pisać sobie własne wykrywanie kolizji tą metodą i oto efekty: http://www.mediafire.com/?5ddo9gsh1ry

EDIT: Zapomnialem ze moj silniczek wymaga jeszcze biblioteki Audiere ktora mozna sciagnac tu: http://audiere.sourceforge.net/download.php

EDIT2: na serwer wgralem juz ZIP z audiere.dll, wiec nie trzeba go sciagac :) [ poprawilem link u gory ]
« Ostatnia zmiana: Lipiec 07, 2007, 14:57:24 wysłana przez Moriturius »

Offline JasonVoorhees

  • Użytkownik
    • FotoGry

# Lipiec 08, 2007, 19:56:59
Dane wejściowe:
(xp,yp) - pozycja gracza
(dx,dy) - przesunięcie gracza

Algorytm
1. Zapamiętaj stare położenie ox=xp, oy=yp,
2. Przesyń gracza w osi X: xp+=dx,
3. Jeżeli wystąpiła kolizja, przywróć stare położenie X: xp=ox,
4. Przesuń gracza w osi Y: yp+=dy,
5. Jeżeli wystąpiła kolizja, przywróć stare położenie Y: yp=oy,

Co prawda trzeba sprawdzac kolizję dwukrotnie, ale gracz będzie się poprawnie "ślizgał" po poziomych i pionowych ścianach (ale takie proste podejście nie zadziała juz dla ścian ukośnych). :)
Działa genialnie :D
Twoją listę kroków napiszę w kodzie jako komentarz z Twoim nickiem z forum :) hehe.
Naprawdę dzięki.