Idealne zderzenie 2 kul

0

witam

próbuje napisać mały programik którego zadaniem jest pokazywanie ruchu 2D dwóch kul w prostokątnym obszarze.
o ile zderzenie ze ściana to nie był problem o tyle z samymi kulami juz takowy mam :/

struct ball
{
   float x, y, vx, vy;
};

to struktura opisująca kule (na razie zakładam że mają te same masy i promienie)
funkcja która rysuje nam kule wygląda tak

static void redraw_screen(void)
{
   move_ball(&app.ball_a);
   move_ball(&app.ball_b);
   
   ball_collision(&app.ball_a, &app.ball_b);

   /* ... */
}

move_ball działa tak jak trzeba (przesuwanie kul + zderzenia ze ściankami)

static void ball_collision(struct ball *ball_a, struct ball *ball_b)
{
   float dx = ball_b->x - ball_a->x;
   float dy = ball_b->y - ball_a->y;
   float d = sqrt(dx*dx+dy*dy);
   
   if(d<=bmap_ball.height) // r1+r2 = bmap_ball.height
   {

      // first we calculate the velocity in the direction of (dx,dy)
      float vd_a = (ball_a->vx*dx + ball_a->vy*dy)/d;
      float vd_b = (ball_b->vx*dx + ball_b->vy*dy)/d;
   
      // collision should have happened dt before;
      float dt =(bmap_ball.height-d)/(abs(vd_a-vd_b));
   
      // we should move those ball backward
      ball_a->x -= ball_a->vx*dt;
      ball_a->y -= ball_a->vy*dt;
      ball_b->x -= ball_b->vx*dt;
      ball_b->y -= ball_b->vy*dt;
   
      dx = ball_b->x - ball_a->x;
      dy = ball_b->y - ball_a->y;
      d = sqrt(dx*dx+dy*dy);

      // calculate the components of velocity
      vd_a = (ball_a->vx*dx + ball_a->vy*dy)/d;
      float vp_a = (ball_a->vx*dy + ball_a->vy*dx)/d;

      vd_b = (ball_b->vx*dx + ball_b->vy*dy)/d;
      float vp_b = (ball_b->vx*dy + ball_b->vy*dx)/d;

      // calculate new velocity for those balls after collision.
      ball_a->vx = (vd_b*dx + vp_a*dy)/d;
      ball_a->vy = (vd_b*dy + vp_a*dx)/d;
      ball_b->vx = (vd_a*dx + vp_b*dy)/d;
      ball_b->vy = (vd_a*dy + vp_b*dx)/d;
      
      // now we need to move time dt forward
      ball_a->x += ball_a->vx*dt;
      ball_a->y += ball_a->vy*dt;
      ball_b->x += ball_b->vx*dt;
      ball_b->y += ball_b->vy*dt;
   }
}

yyh no własnie. dla ścisłości:
vd_a, vd_b - składowe prędkości równoległe do prostej łączącej środki okręgu
vp_a, vp_b - składowe prędkości prostopadłe do ww prostej

dodam że przy niektórych zderzeniach odbicie zachodzi dobrze, jednak przy innych już nie np zwiększa się prędkość, jednak kula zaczyna "gonić " drugą itp

pozdrawiam,
Bartek

PS. dodam jeszcze że czasami położenie kul zmienia się tak bardzo ze wychodzą poza obszar rysowania (zwieszając mi telefon przy okazji :-[ )

0

Zapoznaj się z tymi artykułami. Nie są długie, a powinny pomóc. Po co będę pisał krótko i nieprecyzyjnie na forum, skoro ktoś to już za mnie zrobił o wiele lepiej:

http://www.gamedev.pl/articles.php?x=view&id=166
http://www.gamedev.pl/articles.php?x=view&id=181

0

hmm no tak tylko mamy tam przykład zderzenia centralnego :)

no nic, muszę chyba jeszcze raz przeanalizować kod

0

no tak i po przejrzeniu tych postów mogę jedynie stwierdzić że kod mam poprawny [???]

konkretnie chodzi mi o ten rysunek
user image
oznaczmy
Va, Vb - prędkości kul A,B przed zderzeniem
Va', Vb' - prędkości kul A,B po zderzeniu

Vda, Vdb - składowe prędkości równoległe do prostej łączącej środki kul
Vpa, Vpb - składowe prędkości prostopadłe do prostej...

czyli
Va = Vda + Vpa
Vb = Vdb + Vpb

a po zderzeniu
Va' = Vdb + Vpa
Vb' = Vda + Vpb

dla rozpatrywanego przypadku. gdzie coś przeoczyłem [???]

0

mogę się mylić, ale moim zdaniem zamiast
float d = sqrt(dxdx+dydy);
powinno byc d = abs(dx) + abs(dy)
i
zamiast
float vd_a = (ball_a->vxdx + ball_a->vydy)/d;
float vd_b = (ball_b->vxdx + ball_b->vydy)/d;

powinno być
float vd_a = ( ball_a->vxabs(dx) + ball_a->vyabs(dy))/d;
float vd_b = ( ball_b->vxabs(dx) + ball_b->vyabs(dy))/d;

tak samo wszędzie później zamiast dx i dy trzeba wstawić abs(dx) abs(dy)

U ciebie jeżeli vx jest ujemne, to dx teź, więc iloczyn vx*dx zawsze jest dodatni, więc vd_a i vd_b są zawsze dodatnie, a to chyba jest niepoprawne.

Głowy za to nie daję, ale zawsze możesz spróbować.

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