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

[SFML2] Platformówka a bounding box collision

Ostatnio zmodyfikowano 2015-07-08 14:07
Autor Wiadomość
qest43
Temat założony przez niniejszego użytkownika
[SFML2] Platformówka a bounding box collision
» 2015-06-21 15:32:23
Piszę platformówkę, mam taki system kolizji gdzie wyliczam położenie lewo,prawo,górę,dół od gracza i klocków, potem jeśli kolizja występuję przypisuję odpowiednie położenie:

C/C++
if( player.getSize().intersects( sprite.getGlobalBounds() ) )
{
    float bottom = sprite.getPosition().y + sprite.getGlobalBounds().height;
    float left = sprite.getPosition().x;
    float right = sprite.getPosition().x + sprite.getGlobalBounds().width;
    float top = sprite.getPosition().y;
   
    float pBottom = player.getPosition().y + player.getSize().height;
    float pLeft = player.getPosition().x;
    float pRight = player.getPosition().x + player.getSize().width;
    float pTop = player.getPosition().y;
   
    float prevBottom = player.getPrevPosition().y + player.getSize().height;
    float prevLeft = player.getPrevPosition().x;
    float prevRight = player.getPrevPosition().x + player.getSize().width;
    float prevTop = player.getPrevPosition().y;
   
    if( pBottom >= top )
    {
        sf::Vector2f newPosition;
        newPosition.x = player.getPosition().x;
        newPosition.y = top - 0.1 - player.getSize().height;
       
        player.setPosition( newPosition );
       
    }
    else if( pTop <= bottom )
    {
        sf::Vector2f newPosition;
        newPosition.x = player.getPosition().x;
        newPosition.y = bottom;
       
        player.setPosition( newPosition );
    }
    else if( pRight >= left )
    {
        sf::Vector2f newPosition;
        newPosition.x = left - 0.1 - player.getSize().width;
        newPosition.y = player.getPosition().y;
       
        player.setPosition( newPosition );
       
       
    }
    else if( pLeft <= right )
    {
        sf::Vector2f newPosition;
        newPosition.x = right;
        newPosition.y = player.getPosition().y;
       
        player.setPosition( newPosition );
    }

Problem polega na tym że jak kolizja powinna wystąpić po bokach -lewego lub prawego boku to teleportuje na górę klocka. Szukam rozwiązania tego problemu, bo potrzebuję taki system kolizji żeby też działało przy ruchomych platformach. Znacie jakieś rozwiązanie?
P-133868
pekfos
» 2015-06-21 16:50:01
Najpierw sprawdzaj, jakiego rodzaju jest kolizja (w pionie, poziomie), a potem dopiero sprawdzaj konkretny kierunek.
P-133869
qest43
Temat założony przez niniejszego użytkownika
» 2015-06-21 17:04:01
Ale na postać zawsze działa grawitacja więc trzeba sprawdzać w pionie.
P-133870
Lora
» 2015-06-21 17:21:20
To ci źle działa przez te else if-y. Co się stanie jeśli spełnione są warunki pBottom >= top i pRight >= left naraz? Wykona się tylko działanie dla tego pierwszego warunku i cofnie gracza do góry jednocześnie przesuwając go w poziomie na nową pozycję:
C/C++
if( pBottom >= top )
{
    sf::Vector2f newPosition;
    newPosition.x = player.getPosition().x; // W poziomie przesuwa gracza na niewłaściwą pozycję
    newPosition.y = top - 0.1 - player.getSize().height; // kolizja w pionie zadziała
   
    player.setPosition( newPosition );
   
}
P-133871
qest43
Temat założony przez niniejszego użytkownika
» 2015-06-21 17:27:35
Dla każdego klocka sprawdza z osobna, nie ma takie możliwości żeby  pBottom >= top było TRUE i pRight >= left też TRUE, bo jak jest na samej górze to po prawej może już być tylko inny klocek, a z nowym klockiem już się sprawdzi kolizję osobno.
P-133872
pekfos
» 2015-06-21 17:37:01
nie ma takie możliwości żeby  pBottom >= top było TRUE i pRight >= left też TRUE
Jest możliwe i tego typu przypadki wywołują błąd, który próbujesz rozwiązać.

Ale na postać zawsze działa grawitacja więc trzeba sprawdzać w pionie.
Nie.
P-133873
Lora
» 2015-06-21 17:41:17
Nie wiem jak wygląda struktura twojej gry więc ciężko powiedzieć, ale wydaje mi się, że mam rację. Załóżmy, że bounding box gracza ma parametry:
sf::Rect < float >( 52, 50, 30, 30 )
, a bounding box jakiegoś klocka po prawej:
sf::Rect < float >( 85, 50, 50, 30 )
. Klikasz strzałkę w prawo i przesuwasz gracza np. o 5 pikseli w prawo. Teraz mamy:
pBottom = 80, pRight = 87, top = 50, left = 85. Sprawdzamy kolizję:
if( pBottom >= top ) - Prawda

no to wykonujemy działanie:
newPosition.x = player.getPosition().x = 57
newPosition.y = top - 0.1 - player.getSize().height = 19.9 // Poprzednia pozycja była równa 50!
Wynik - teleportacja.

A warunek( pRight >= left ) też jest prawdą ale się nie wykona, bo jest po elsie.
 
P-133874
pekfos
» 2015-06-21 17:53:04
Oblicz rozmiar części wspólnej bounding boxa platformy i postaci gracza. Jeśli jest szersza, niż wyższa, to zderzenie nastąpiło z góry lub z dołu, w przeciwnym wypadku było z boku. Dla każdego z tych dwóch przypadków sprawdzasz tylko konkretny kierunek i teleportujesz postać do odpowiedniej krawędzi. Dodatkowo, jeśli nie ma żadnej kolizji, to wyjdą ci zera w rozmiarze części wspólnej, więc możesz tym zastąpić także główny warunek player.getSize().intersects(sprite.getGlobalBounds()).
P-133875
« 1 » 2 3
  Strona 1 z 3 Następna strona