Allegro C++ kolizje okręgi problem

0

Witam!
Mam następujący problem. Otóż robiłem ostatnio w Allegro programik, który ma wykrywac kolizję między okręgami. Wrzucę najpierw kodzik, a potem wyjaśnię

float A,B,C,D;
float d;
struct okrag{
       int x,y,px,py;
       int r;
       bool czy_kol;
       int operator==(const okrag &o){return x==o.x && y==o.y && px==o.px && py==o.py && r==o.r;}
       };

bool czy_kolizja(okrag P,okrag Q){
     if(P.r+Q.r>=sqrt((P.x-Q.x)*(P.x-Q.x)+(P.y-Q.y)*(P.y-Q.y)))return 1;
     else{
     bool czy=0;
     A=(P.x*P.x)+(Q.x*Q.x)-(2*P.x*Q.x)+(P.y*P.y)+(Q.y*Q.y)-(2*P.y*Q.y);
     B=2*((P.x*P.px)-(P.x*Q.px)-(P.px*Q.x)+(Q.x*Q.px)+(P.y*P.py)-(P.y*Q.py)-(P.py*Q.y)+(Q.y*Q.py));
     C=P.x*P.x+Q.x*Q.x-(2*P.x*Q.x)+P.y*P.y+Q.y*Q.y-(2*P.y*Q.y)-((P.r+Q.r)*(P.r+Q.r));
     D=B*B-4*A*C;
     
     if(D>=0){
     float x1,x2;
     x1=(-B+sqrt(D))/(2*A);
     x2=(-B-sqrt(D))/(2*A);
     if((0<=x1 && x1<=1) || (0<=x2 && x2<=1))czy=1;
              }
     return czy;}
     };
 

Mamy tu strukturę okrag, która przechowuje informację o naszym okręgu i tak x,y to wspołrzedne środka, r promień px, py to składowe wektora prędkości. Funkcja czy_kolizja ma za zadanie sprawdzić czy w trakcie trwania jednej klatki gry zaszła kolizja. Tj. najpierw sprawdza czy okręgi kolidują ze sobą na poczatku trwania klatki, a następnie czy w momencie od początku danej klatki do początku drugiej okręgi w międzyczasie się gdzieś nie zdeżyły.

No i problem jest następujący: nawet jeśli wartości A,B,C czyli wspołczynniki równania kwadratowego wyjdą takie, że delta powinna być zerowa to jednak w tej funkcji wartość delty wychodzi ujemna przy czym wychodzi ona w postaci np. D=-9,17564e+015 czy jakoś tak. I to wszystko sprawia, że mimo iż kolizja między okręgami zachodzi, to funkcja ta jej nie wykrywa.

Dla przykładu:

okrag Aa={200,50,0,0,10},Bb={188,300,0,-3,2};
     
     while(!key[KEY_ESC]){
     while(szybkosc>0){
//     clear_bitmap(bufor);
     
     
     
      
    
     
     circlefill(bufor,(int)(Bb.x),(int)(Bb.y),Bb.r,makecol(255,0,0));
     circlefill(bufor,(int)(Aa.x),(int)(Aa.y),Aa.r,makecol(255,255,0));

     if(czy_kolizja(Aa,Bb)){
     circlefill(bufor,500,100,5,makecol(255,0,255));
     
                          }
                          
                        
     if(D<0)plik << "D<0  ";
     plik << "y=" << Bb.y << "  A=" << A <<"   B=" << B << "   C=" << C << "   D=" << D  <<"   X1=" << (-B+sqrt(D))/(2*A) << "   X2=" << (-B-sqrt(D))/(2*A) <<endl;
     

     blit(bufor,screen,0,0,0,0,bufor->w,bufor->h);
     
     Bb.y=Bb.y+Bb.py;
     
     
     szybkosc--;}
 

Celowo bufor jest nieczyszczony po każdym obiegu pętli, aby uwidocznić zajście kolizji.

Przy pisaniu tej funkcji korzystałem z

http://wiki.gamedev.pl/Kolizja_w_czasie

Z góry dziękuję za pomoc.

0

nie sprawdzane:

bool czy_nachodza(int x1,int y1,int r1,int x2,int y2,int r2) {
  double odl_srodkow = sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1));
  czy_nachodza = odl_srodkow<=r1+r2;
}

void wykonaj_krok(okrag &O) {
  O.x+=O.px;
  O.y+=O.py;
  O.px=0;
  O.py=0;
}

bool czy_kolizja(okrag P,okrag Q){
  if czy_nachodza(P.x,P.y,P.r, Q.x,Q.y,Q.r)
    return true;
  wykonaj_krok(P);
  wykonaj_krok(Q);
  if czy_nachodza(P.x,P.y,P.r, Q.x,Q.y,Q.r)
    return true;
  return false;
}
0

Z tego co widzę (jesli dobrze widzę), to Twój program sprawdza czy zaszła kolizja następnie przesuwa okręgi o wektor prędkości, a potem znów sprawdza czy zaszła kolizja czyli innymi słowy robi to co by się wykonało w następnej klatce i niekoniecznie musi on wykryc kolizję nawet jeśli zaszła gdyż wektory prędkości mogą być takie, ze okregi po prostu się przeskoczą mimo iz gdyby poruszały się w czasie ciągłym to by się zdeżyły, a tak kolizja nie zostanie wykryta...

I mi chodziło o to, że mój problem nie był z algorytmem gdyż ten był dobry raczej tylko z tym jak program wyliczał zwłaszcza deltę otrzymanego równania kwadratowego. Ale już sobie z tym poradziłem.

1
boo czyBedzieKolizja(const okrag& a, const okrag& b)
{
    int sumaR = a.r + b.r;
    int dx = b.x - a.x;
    int dy = b.y - a.y;
    int vx = b.px - a.px;
    int vy = b.py - a.py;

    if (dx*dx+dy*dy<=sumaR*sumaR) {
        return true; // już jest kolizja
    }
    if (vx==0 && vy==0) {
         return false; // stoją więc się będzie już kolizji
    }

    if (abs(vx*dy-vy*dx)>sumaR*sqrt(vx*vx+vy*vy)) {
         return false; // kolizji nie było i nie będzie
    }
    // kolizja była lub będzie, ale nas interesuje tylko będzie lub jest
    return vx*dx+vy*dy<0;
}

1 użytkowników online, w tym zalogowanych: 0, gości: 1