2016-02-27 24 views
5

W Javie piszę aplikację mobilną dla systemu Android, aby wchodzić w interakcję z dynamicznymi piłkami z klasami, które sam napisałem. Grawitacja jest określana na pochylenie telefonu.Zderzenia koła fizyki uderzające i przesuwające się na granicy

Zauważyłem, gdy mam pęk kulki w kącie, że niektóre z nich zaczną drgać, a czasami ślizgają się, zderzając się z innymi kulkami. Czy to możliwe, ponieważ wykonuję kroki w niewłaściwej kolejności?

Teraz mam jedną pętlę przechodzi każdą piłkę do:

  • Sim iteracji
  • Sprawdź kolizje z innymi kulkami
  • Sprawdź kolizji na scenie granic

powinienem dodaj, że mam tarcie z granicami i kiedy dochodzi do kolizji piłki z piłką, by stracić energię.

Oto fragment kodu, jak kolizja jest obsługiwane:

// Sim an iteration 
    for (Ball ball : balls) { 
     ball.gravity.set(gravity.x, gravity.y); 

     if (ball.active) { 
      ball.sim(); 

      // Collide against other balls 
      for (Ball otherBall : balls) { 
       if (ball != otherBall) { 
        double dist = ball.pos.distance(otherBall.pos); 
        boolean isColliding = dist < ball.radius + otherBall.radius; 
        if (isColliding) { 
         // Offset so they aren't touching anymore 
         MVector dif = otherBall.pos.copy(); 
         dif.sub(ball.pos); 
         dif.normalize(); 
         double difValue = dist - (ball.radius + otherBall.radius); 
         dif.mult(difValue); 
         ball.pos.add(dif); 

        // Change this velocity 
        double mag = ball.vel.mag(); 
        MVector newVel = ball.pos.copy(); 
        newVel.sub(otherBall.pos); 
        newVel.normalize(); 
        newVel.mult(mag * 0.9); 
        ball.vel = newVel; 

        // Change other velocity 
        double otherMag = otherBall.vel.mag(); 
        MVector newOtherVel = otherBall.pos.copy(); 
        newOtherVel.sub(ball.pos); 
        newOtherVel.normalize(); 
        newOtherVel.mult(otherMag * 0.9); 
        otherBall.vel = newOtherVel; 
        } 
       } 
      } 
     } 
    } 
+0

Czy możemy zobaczyć, co zrobiłeś do tej pory? – Dan

+0

Czy testujesz w teście zderzeniowym, czy oba obiekty przesuwają się w kierunku siebie? Czy obliczacie dokładne czasy kolizji, czy pozwalacie na przesuwanie się obiektów? – LutzL

+0

Zaktualizowany za pomocą kodu. Nie testuję, czy dwa obiekty zbliżają się do siebie. W tej chwili pozwalam, aby kule poruszały się w sobie, a następnie reagowały na kolizję. –

Odpowiedz

2

Jeśli jest to tylko kod, który sprawdza interakcji pomiędzy kulkami, problem wydaje się dość oczywiste. Nie ma możliwości, by piłka znalazła się na innej kuli, w równowadze.

Załóżmy, że masz jedną piłkę bezpośrednio nad drugą. Podczas obliczania przyspieszenia górnej piłki z powodu grawitacji powinieneś także wykonać test kolizji, taki jak ten, który opublikowałeś, z wyjątkiem tego sprawdzania czasu na dist <= ball.radius + otherBall.radius. W takim przypadku powinieneś przyjąć normalną siłę pomiędzy kulkami równą grawitacji i zanegować składową grawitacji zgodnie z wektorem łączącym dwa centra piłek. Jeśli tego nie zrobisz, górna kula przyspieszy do dolnej, uruchamiając kod kolizji, który wysłałeś, a dostaniesz roztrzęsienia.

Podobna logika musi być używana, gdy piłka styka się ze sceną.

+0

Myślę, że rozumiem, do czego zmierzasz, ale mam problem z ustaleniem reakcji kolizji. Powiedzmy, że mam 'ball1' na górze' ball2'. Przed simmingem 'ball1', testuję go przeciwko' ball2', ​​aby sprawdzić, czy już się dotykają. Jeśli tak, to muszę dostosować pozycję "kulki 1" i dostosować kierunek grawitacji tak, aby jej nie przechodziła? –

+0

Twoja regulacja pozycji jest w porządku; jest to grawitacja, którą trzeba dostosować, ponieważ przeciwstawiałaby się ona normalnej sile pomiędzy dwiema kulkami. Jeśli więc kulka 1 dotyka kulki 2, a wektorowa iloczyn grawitacji piłki 1 (g) z wektorem (v) wskazującym od kulki 1 do kulki 2 jest dodatnia, to należy odjąć od wektora grawitacji kuli1 v razy (g kropka v)/v^2). To jest składnik wektora grawitacji, który jest w kierunku v. –

1

Od czasu, gdy eksperymentowałem z własnym silnikiem Phys2D (tylko dla zabawy), wiem, że mówisz. (Na wszelki wypadek - możesz sprawdzić moje demo tutaj: http://gwt-dynamic-host.appspot.com/ - wybierz "Dema kółka kolizji" tam i odpowiedni kod tutaj: https://github.com/domax/gwt-dynamic-plugins/tree/master/gwt-dynamic-main/gwt-dynamic-module-bar).

Problem ma charakter iteracji i nieskończonej pętli powodujących kolizję konsekwencji. Kiedy np. do kuli dojdzie do kuli, doświadcza co najmniej 3 wektory siły: impuls odbicia od ściany, impulsu odbicia od podłogi i impulsu grawitacji - po podsumowaniu wszystkich 3 impulsów, zmniejsz ją zgodnie z algorytmem utraty energii, mieć nowy wektor, w którym powinna być twoja piłka. Ale np. ten impuls kieruje go na ścianę - wtedy musisz ponownie obliczyć zbiór wektorów zgodnie z wszystkimi rzeczami: energia odbicia, impulsy, grawitacja, itp. Nawet w przypadku, gdy wszystkie te impulsy są małe, nigdy nie otrzymasz wszystkich 0 , ze względu na precyzję podwójnych i twoje stałe porównania tolerancji - to dlatego, że masz efekty "jittera" i "przesuwania".

Faktycznie, większość z istniejących silników 2D mają te skutki takiego czy innego rodzaju: możesz je zobaczyć tutaj: http://brm.io/matter-js/demo/#wreckingBall lub tutaj: http://box2d-js.sourceforge.net/index2.html - oni właściwie tylko zrobić małe impulsy być wchłaniane szybciej i zatrzymać Iterowanie kiedy cały system staje się mniej lub bardziej stabilny, ale nie zawsze jest to możliwe.

W każdym razie, chciałbym polecić nie wymyślać własnego koła, chyba że jest to tylko dla twojej zabawy - lub dla lepszego zrozumienia tego.

Na ostatnim (JFF) - tutaj jest dobry tutorial: http://gamedevelopment.tutsplus.com/tutorials/how-to-create-a-custom-2d-physics-engine-the-basics-and-impulse-resolution--gamedev-6331

Dla prawdziwych rzeczy, polecam korzystanie z istniejących silników, np Unity (https://unity3d.com/learn/tutorials/modules/beginner/2d/physics2d) lub Box2d (http://box2d.org/)

Mam nadzieję, że to pomoże.

+0

Dzięki za referencje! Zacznę w nie zaglądać. –

1

Iterowanie przez wszystkie piłki i zmiana pozycji piłki dla każdej iteracji jest prawdopodobnie przyczyną niestabilności, przesuwasz piłkę w lewo, aby uniknąć kolizji po prawej, a następnie popchnąłeś piłkę w inną piłkę po lewej, a następnie lewa kula próbuje ją z powrotem wcisnąć.

Z góry mojej głowy mógłbym polecić próbę podsumowania wszystkich sił na każdej z piłek, zanim zrobisz cokolwiek z pozycjonowaniem. A jeśli wykonasz iterację z kulki "na górze" (najdalej od źródła/kierunku grawitacji), prawdopodobnie uzyskasz stabilną sytuację.

Zasadniczo, górna kula musi najpierw obliczyć siły pomiędzy sobą i kulą (-ami) pod nią, a także grawitację, a następnie podaną kulą będzie wiedzieć, ile siły pochodzi z górnej kuli i dodana grawitacyjnie również dodać do siły, której naciska kulki pod nią. Kiedy wszystkie kule będą znały siły, z którymi są przepychane, możesz przekształcić tę siłę w ruch.

1

Sposób, w jaki symulujesz fizykę kulek, może powodować niestabilność. Rozdzielczość kolizji próbuje oddzielić kulki przez rzutowanie jednego z nich w przeciwnym kierunku przez głębokość kolizji. To może naprawić zakładkę dla tych dwóch piłek, ale szanse są (szczególnie, gdy piłki są ułożone), że piłka teraz nakłada się na inną piłkę.

Istnieje wiele sposobów na naprawienie penetracji. Jednym z najprostszych sposobów jest dodanie "uprzedzenia" lub trochę nacisku na oba ciała, aby zmusić je do rozdzielenia w ciągu następnych kilku ramek. Pozwala to tej energii na rozprzestrzenianie się i rozłączanie wszystkich ciał. Problem polega na tym, że uprzedzenia często się przeceniają i powodują odrobinę odskoku. Aby rozwiązać ten problem, zaleciłbym odczytywanie impulsu sekwencyjnego.

Dostosowanie wyglądu fizycznego do rzeczywistości nie jest tak proste, jak mogłoby się wydawać. Jeśli nie masz nic przeciwko niestabilności, polecam poświęcić trochę czasu na czytanie różnych technik lub używanie silnika takiego jak Box2D.

+0

Zgadzam się, muszę popchnąć oba, zamiast tylko jednego. Czy nie pchając obydwu, nadal istnieje możliwość, że obaj będą nachodzić na inne piłki? Zastanawiam się, czy powinienem najpierw rozwiązać kule, które są najbliżej linii i dotrzeć do środka. Przeczytam więcej o tym, o czym wspomniałeś, to wydaje się być bardzo trudne! –

+0

@ GreenCell Odchylenie nie jest projekcją. Jest to siła zastosowana do obu ciał. Oznacza to, że gdy pojawi się następna przepustowość rozdzielczości, energia będzie się rozprzestrzeniać. Zakładam, że używasz rozdzielczości impulsu. Jeśli nie, polecam lekturę. – py13579