Kolizja koło-koło (circle-circle)

0

Witam,

Szukam optymalnego algorytmu do sprawdzania kolizji koła z kołem.
Niezależnie jakiego promienia są obiekty. Miło by było jakby można było określić również masę obiektu. Koła poruszają się ruchem przyśpieszonym - stosuję do tego 4 prędkości (velocityX, ...X2, velocityY, ...Y2) - próbowałem dwoma, ale działało mi tylko na poruszanie 'dodatnie' dla X i Y. Zresztą nie moim problemem jest ruch obiektów (kolegi problem, sam napisałem byle co aby można było doświadczalnie pisać kolizję), lecz kolizja tylko i wyłącznie, i na tym wolałbym się skupić. :)

    private void collision(){
        temp.setPosition(x+velocityX, y);
        if(temp.overlaps(coll2)){
            velocityX=0;            
        }
        temp.setPosition(x+velocityX2, y);
        if(temp.overlaps(coll2)){
            velocityX2=0;            
        }
        temp.setPosition(x, y+velocityY);
        if(temp.overlaps(coll2)){
            velocityY=0;         
        }
        temp.setPosition(x, y+velocityY2);
        if(temp.overlaps(coll2)){
            velocityY2=0;            
        }
    }

Stosuje tymczasową zmienną Circle temp, aby sprawdzać jeszcze przed kolejnym FPS-em kolizję. Obiekt faktycznie zatrzymuje się na drugim obiekcie, jednak często utyką w nim lub całkowicie traci prędkość (nie odbija się, czy też nie leci wzdłuż kolizji płynnie).

Za jakąkolwiek pomoc, linki, info - dziękuję z góry! :)

0

Oblicz odległość między punktami środka kół. Jeśli jest <= niż suma ich promieni to się 'stykają' lub na siebie zachodzą.

0

Nie to mnie martwi. Wzór na obliczanie odległości między dwoma punktami jest prosty do napisania i użycia. Nie wiem co powinienem wykonywać gdy dojdzie do tej kolizji i jak obiekt ma się płynnie poruszać wokół drugiego koła, który załóżmy, że stoi w miejscu i nie działają na niego żadne siły odpychające - jest statyczny/martwy.

0

Jeśli robisz gierkę wykorzystującą fizykę, to skorzystaj z gotowego rozwiązania np Box2D.

0

Dzięki za propozycję, mam nawet pdf do nauki, ale wolałbym na chwilę obecną zrozumieć i wykonać to bez użycia bibliotek czy silników 2D :)

0

W takim razie zacznij od wytłumaczenia przynajmniej sobie co chcesz osiągnąć.

0

Objekt czerwony jest obiektem poruszanym, natomiast zielony stoi w miejscu jak słupek.

Cały problem polega na tym jak należy napisać funkcję sprawdzającą kolizję wzdłuż okręgu zielonego.

Funkcje jakimi mogę się posłużyć to m.in overlaps(), contains(), ale mogę zastosować odległość punktową (odl=pierwiastek2(x1-x2)2+(y1-y2)2)), uwzględniając przy tym promień objektów i tym sposobem sprawdzenie czy nachodzą na siebie, czyli if(odl<=promien1+promien2) zachodzi kolizja.

0

czyli if(odl<=promien1+promien2) zachodzi kolizja

Z tego co widzę to koło czerwone porusza się swoim środkiem po łuku okręgu o promieniu r1+r2 i środku w środku koła zielonego, do pewnego momentu - aż kąt między pierwotnym wektorem ruchu a odcinkiem łączącym oba środki osiągnie 90° (zgaduję, bo nie wyjaśniłeś co ma się dziać dalej).

0

Dokładnie o to chodzi - okrąg czerwony ma się poruszać/ocierać idealnie po krawędzi okręgu zielonego, oczywiście płynnie, bo sam napisałem coś w rodzaju wstępnej kolizji i obiekt czerwony zacina się lub kompletnie utyka w obiekcie zielonym.

Nie wiem czy łamię regulamin podając tytuł gry przeglądarkowej: Haxball (w razie czego usunąc nazwe i upomnieć :D ) - szukam skryptu lub opracowania do napisania podobnej kolizji jaka występuje w tej grze.

Znalazłem ciekawy artykuł: http://gamedevelopment.tutsplus.com/tutorials/when-worlds-collide-simulating-circle-circle-collisions--gamedev-769, jednak tutaj wszystko działa na odbijaniu się od siebie ciał sprężystych.

0

Takie zachowanie wynika z roznicy kierunkow sil, sila wieksza -> user naciera na kulke przeciwnika, sila mniejsza -> kulka przeciwnika reaguje na przylozona sile. W gruncie rzeczy, obie sily sa podobnej wartosci, stad efekt przesuwanie sie kulki po okregu drugiej kulki. Znajdz poprawny algorytm wyliczania sily odbicia i dobierz odpowiednie wspolczynni dla twojego swiata, a takie zachowanie bedziesz mial w gratisie. Natomiast wystepuja ono tylko wtedy, gdy sily te nie maja tego samego kierunku.

1

Narysowałem taki schemat:
28116cdb08.png

Wektor prędkości (niebieski) rozkładasz na dwa wektory (czarny i brązowy)
Zielona kula "oddaje" w większym stopniu wektor czarny (zależy od sprężystości, można przyjąć 100%),
zaś prawie nie reaguje na brązowy (zależy od tarcia, można przyjąć 100%).

Nowa prędkość kuli brązowy minus czarny.
Czołowe zderzenie to też możesz liczyć wg tej samej zasady, wyjdzie na to samo ponieważ brązowa składowa będzie zerowa.

0

Znalazłem taki materiał na Wikipedii: http://en.wikipedia.org/wiki/Elastic_collision w ostatnim akapicie "Two-Dimensional Collision With Two Moving Objects".

Więc posłużyłem się tym wzorem, ale mam do tego pewne wątpliwości:

  1. czy właściwie podstawiłem kąty do danych (sprawdzając metodą System.out.print() działało wszystko w porządku):
angleColRad = Math.atan2(y - sp.getY(), x - sp.getX());  //sprawdzam kąt wzgledem obiektu kolizyjnego
        angleColDeg = Math.toDegrees(angleColRad);  //uzyje je i porownam do wzoru w kolizji miedzyobiektowej;
        if (angleColDeg < 0) {
            angleColDeg += 360;
        }

        angleMovRad = Math.atan2((y - lasty), (x - lastx));
        angleMovDeg = Math.toDegrees(angleMovRad);
        if (angleMovDeg < 0) {
            angleMovDeg += 360;
        }

sp -> jest to tak samo obiekt koło (argument funkcji collisionCircles()), z którym co fps porównuje, czy zachodzi z nim kolizja - z nim ingeruje główny obiekt koło;
angleMovDeg -> kąt ruchu kółka, pobieram poprzednią pozycję i kiedy ruszam w górny prawy róg wartość wynosi 45, jak w prawo to 0, w lewo 180, w dol 270;
angleColDeg -> kąt kolizyjny dwóch kółek, podobnie jak wyżej zwraca kąty wzgledem obiektu sp, górny prawy róg 45 itd;

Wcześniej kąty zwracały wartości od -179 do 180, więc dodałem warunek, który wszystkie wartości ujemne zamienia na ich odpowiedniki plusowe, tzn. kąt -1 to kąt 359, jednak i to nie pomogło :(
Wartości ujemne znajdowały się na ćwiartkach IV i III, w tym, że wartości na IV były od -1 do -90, natomiast na III od -90 do -179

  1. czy dobrze go napisałem jako formuła w strukturze:
            float newSpeedx1 = (float) (((speedx * Math.cos(angleMovDeg - angleColDeg) * (mass - sp.getMass())
                    + (2 * sp.getMass() * sp.getSpeedx() * Math.cos(sp.getAngleMovDeg() - angleColDeg))) / (mass + sp.getMass()))
                    * Math.sin(angleColDeg) + (speedx * Math.sin(angleMovDeg - angleColDeg) * Math.sin(angleColDeg + (180 / 2))));
            float newSpeedy1 = (float) (((speedy * Math.cos(angleMovDeg - angleColDeg) * (mass - sp.getMass())
                    + (2 * sp.getMass() * sp.getSpeedy() * Math.cos(sp.getAngleMovDeg() - angleColDeg))) / (mass + sp.getMass()))
                    * Math.sin(angleColDeg) + (speedy * Math.sin(angleMovDeg - angleColDeg) * Math.sin(angleColDeg + (180 / 2))));
float newSpeedx2 = (float) (((sp.getSpeedx() * Math.cos(sp.getAngleMovDeg() - angleColDeg) * (sp.getMass() - mass)
                    + (2 * mass * speedx * Math.cos(angleMovDeg - angleColDeg))) / (sp.getMass() + mass))
                    * Math.sin(angleColDeg) + (sp.getSpeedx() * Math.sin(sp.getAngleMovDeg() - angleColDeg) * Math.sin(angleColDeg + (180 / 2))));
            float newSpeedy2 = (float) (((sp.getSpeedy() * Math.cos(sp.getAngleMovDeg() - angleColDeg) * (sp.getMass() - mass)
                    + (2 * mass * speedy * Math.cos(angleMovDeg - angleColDeg))) / (sp.getMass() + mass))
                    * Math.sin(angleColDeg) + (sp.getSpeedy() * Math.sin(sp.getAngleMovDeg() - angleColDeg) * Math.sin(angleColDeg + (180 / 2))));

sp -> jak wyżej obiekt, z którym może dojść do kolizji.
newSpeedx1 -> nowa predkosc, ktora zostanie przypisana do zmiennej speedx;
newSpeedy1 -> nowa predkosc, ktora zostanie przypisana do zmiennej speedy;
newSpeedx2 -> analogicznie do sp.speedx
newSpeedy2 -> analogicznie do sp.speedy

W efekcie obiekty zatrzymują się w sobie, czasem odbiją się na oko w porządku lub tak jakby źle określało kąt odbicia (w przypadku kolizji ponownie wpadają na siebie) - stąd podejrzewam, że problem dotyczy kątów lub całej formuły.

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