Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

[SFML 2.1] Kolizja z nieregularnym kształem (bounding)

Ostatnio zmodyfikowano 2015-02-11 19:42
Autor Wiadomość
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:
C/C++
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
P-126358
maly
» 2015-02-11 18:11:13
C/C++
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
C/C++
sf::RectangleShape Rect( sf::Vector2f( 100, 200 ) );

sf::CircleShape Circle( 50 );
Circle.setOrigin( Circle.getRadius(), Circle.getRadius() ); // musi byc wycentrowane

if( collideCircleRect( Circle, Rect ) )
{
    // kolizja
}
P-126366
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 :)
P-126372
« 1 »
  Strona 1 z 1