[SFML 2.1] Kolizja z nieregularnym kształem (bounding)
Ostatnio zmodyfikowano 2015-02-11 19:42
przemek6 Temat założony przez niniejszego użytkownika |
[SFML 2.1] Kolizja z nieregularnym kształem (bounding) » 2015-02-11 17:35:21 Załóżmy że po włączeniu gry jakiś obiekt (np. piłka) spada na dół metodą move(0, 1). Po pewnym czasie piłka styka się z płaską, równą powierzchnią. By piłka się zatrzymała wystarczy sprawdzić czy zaszedł kontakt między piłką a podłożę. Oczywiście jako początkujący robię to pisząc coś takiego: if( obwiednia_pilki.inersect( obwiednia_podloza ) ) { } else move( 0, 1 )
Czyli piłka spada w dół dopóki nie ma kontaktu z podłożem. Dotąd wszystko działa. A teraz jest problem. Co będzie jak nasze podłoże(niech to będzie zwykły kwadrat) obrócimy wokół jego środka w prawo o 45 stopni. Wtedy powstanie oczywiście coś w rodzaju pagórka. Chcemy by nasza piłka spadła na tą pochyloną już nawierzchnię. I tu jest problem. Obwiednia w SFML to taki najmniejszy prostokąt który obejmie całą figurę czy sprite. A w dodatku zawsze ta obwiednia jest w idealnym poziomie, nigdy się nie obróci razem z figurą. Przez to jak na początku miałem podłoże o bokach a*a i obwiedni również a*a, tak po jego obróceniu o 45 stopni ma już obwiednie o bokach d*d, gdzie d to przekątna kwadratu o boku a. Teraz spadająca piłka zatrzyma się we właściwy sposób tylko wtedy, gdy spadnie idealnie na górny róg kwadratu. Gdy będziemy chcieli by spadła trochę bardziej w lewo (na pochyloną nawierzchnię) to piłka nie zetknie się z tą nawierzchnią tylko zawiśnie w powietrzu gdzieś na wysokość górnego rogu kwadratu. Oczywiście nie ma tu żadnej magii, bo to bounding(obwiednia) decyduje kiedy piłka się zatrzyma. A ta obwiennia nie pokrywa się z naszym kwadratem, jest większy i idealnie poziomy(to kwadrat więc i zarazem idealnie pionowy:)) Nie trzeba chyba wspominać jak wygląda obwiednia piłki. To kwadrat o boku równym średnicy piłki (koła). Jak zaradzić na taki problem i sprawić by zachodził kontakt między widocznymi obiektami (nawet pochylonymi i o nieregularnych kształtach), a nie boundingami? Z góry dziękuję za pomoc PS. Jak nie wiecie o co mi chodzi to mam tu mały rysunek: http://wrzucaj.net/images/2015/02/11/bounding.png |
|
maly |
» 2015-02-11 18:11:13 bool intersects( float cx, float cy, float radius, float left, float top, float right, float bottom ) { float closestX =( cx < left ? left:( cx > right ? right: cx ) ); float closestY =( cy < top ? top:( cy > bottom ? bottom: cy ) ); float dx = closestX - cx; float dy = closestY - cy; return( dx * dx + dy * dy ) <= radius * radius; }
bool collideCircleRect( const sf::Vector2f & CirclePositon, float Radius, const sf::FloatRect & Rectangle ) { return intersects( CirclePositon.x, CirclePositon.y, Radius, Rectangle.left, Rectangle.top, Rectangle.left + Rectangle.width, Rectangle.top + Rectangle.height ); }
bool collideCircleRect( const sf::CircleShape & circle, const sf::RectangleShape & rect ) { sf::Vector2f transpos = rect.getInverseTransform().transformPoint( circle.getPosition() ); return collideCircleRect( transpos, circle.getRadius(), rect.getLocalBounds() ); } Użycie sf::RectangleShape Rect( sf::Vector2f( 100, 200 ) );
sf::CircleShape Circle( 50 ); Circle.setOrigin( Circle.getRadius(), Circle.getRadius() );
if( collideCircleRect( Circle, Rect ) ) { } |
|
przemek6 Temat założony przez niniejszego użytkownika |
» 2015-02-11 19:42:30 Ciekawe, nie chciałem od razu całego gotowego rozwiązania, ale dobra, spróbuję to obczaić i zastosować to w swoim programie:. Dzięki :)
|
|
« 1 » |