Jadranko Temat założony przez niniejszego użytkownika |
[SFML] detekcja kolizji między okręgami » 2016-05-14 23:31:20 Cześć! Tworzę grę a'la Haxball i mam problem z detekcją dwóch okręgów (piłkarza i piłki). Korzystam z twierdzenia pitagorasa i kolizja działa jeżeli piłkarz styka się z piłką w 0 stopniach, 90, 180, 270 oraz ich okolicach. Problem następuje, gdy piłkarz zbliża się do piłki pod kątem pośrednim czyli np 45, 135 itp... (jednocześnie wciskając np strzałkę w dół i w prawo). wtedy piłkarz wchodzi na piłkę i kolizje wariują. static void czyKolidujePilka( player & gracz, player & pilka, sf::Vector2f ruch ) { sf::Vector2f dist1 = gracz.srodekPilkarz(); sf::Vector2f dist2 = pilka.srodekPilka(); sf::Vector2f dist = gracz.srodekPilkarz() - pilka.srodekPilka(); float rad1, rad2, rad; rad1 = gracz.promienPilkarz(); rad2 = pilka.promienPilka(); rad = rad1 + rad2; float d = sqrt( pow( dist1.x - dist2.x, 2 ) + pow( dist1.y - dist2.y, 2 ) ); if( d < rad ) { if( ruch.x > 0 ) { pilka.ruchPilki( sf::Vector2f( ruch.x, 0 ) ); } else if( ruch.x < 0 ) { pilka.ruchPilki( sf::Vector2f( ruch.x, 0 ) ); } else if( ruch.y > 0 ) { pilka.ruchPilki( sf::Vector2f( 0, ruch.y ) ); } else if( ruch.y < 0 ) { pilka.ruchPilki( sf::Vector2f( 0, ruch.y ) ); } } } A druga sprawa, to poruszanie się piłkarza wraz z piłką. Nie mam pojęcia jak mogę zrobić poruszanie się piłki, bo ona porusza się wyłącznie pod kątami prostymi (0, 90, 180, 270). |
|
pekfos |
» 2016-05-14 23:37:14 if( ruch.x > 0 ) { pilka.ruchPilki( sf::Vector2f( ruch.x, 0 ) ); } else if( ruch.x < 0 ) { pilka.ruchPilki( sf::Vector2f( ruch.x, 0 ) ); } else if( ruch.y > 0 ) { pilka.ruchPilki( sf::Vector2f( 0, ruch.y ) ); } else if( ruch.y < 0 ) { pilka.ruchPilki( sf::Vector2f( 0, ruch.y ) ); } |
Jaki to ma cel? |
|
Jadranko Temat założony przez niniejszego użytkownika |
» 2016-05-14 23:42:09 Ten fragment kodu odpowiada za poruszanie się piłki, jeżeli d < rad to w zależności od ruchu piłkarza piłka porusza się w tym samym kierunku. Jeżeli piłkarz biegnie w prawo to znaczy że x jest dodatni więc piłka też porusza się w tym samym kierunku. Oto kod, w którym piłkarz koliduje ze ścianami, gdzie V to zbiór wszystkich ścian(białych linii): static void czyKoliduje( player & g1, std::vector < player > V, sf::Vector2f ruch ) { sf::FloatRect X = g1.doKolizjiPilkarz(); sf::FloatRect Y = g1.doKolizjiPilkarz(); X.left += ruch.x; Y.top += ruch.y; bool kolX = false; bool kolY = false; for( int i = 0; i < V.size(); i++ ) { if( i < V.size() ) { if( X.intersects( V[ i ].doKolizjiPrzeszkoda() ) ) kolX = true; else if( Y.intersects( V[ i ].doKolizjiPrzeszkoda() ) ) kolY = true; } } if( !kolX ) g1.ruch( sf::Vector2f( ruch.x, 0 ) ); if( !kolY ) g1.ruch( sf::Vector2f( 0, ruch.y ) ); } |
|
pekfos |
» 2016-05-14 23:46:06 Ale czemu nie pilka.ruchPilki(ruch)? |
|
Jadranko Temat założony przez niniejszego użytkownika |
» 2016-05-14 23:56:43 Racja, działa. Zrobiłem jeszcze kilka if'ów i już w miarę to wygląda, dzięki ;) |
|
Jadranko Temat założony przez niniejszego użytkownika |
» 2016-05-14 23:57:36 Jeszcze kwestia detekcji kolizji, czy jakoś można precyzyjniej je wykrywać między okręgami? Czy tylko można się opierać na tw. Pitagorasa? |
|
pekfos |
» 2016-05-15 00:15:27 Można to robić efektywniej, operując na kwadracie odległości, a nie samej odległości. Pierwiastkowanie jest dość kosztowne, w porównaniu do mnożenia. |
|
« 1 » |