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

[SFML 2.0] Kolizja (koncepcje)

Ostatnio zmodyfikowano 2012-12-17 11:45
Autor Wiadomość
krzyk
Temat założony przez niniejszego użytkownika
[SFML 2.0] Kolizja (koncepcje)
» 2012-12-14 19:01:00
Wielokrotnie przewiją się przez to forum tematy o kolizji więc podzielę się moją koncepcją,niestety niedziała przy  szybkiej zmianie pozycji(przeskakuje lub wpada w objekty) i niemam na to żadnego pomysła.
Jeśli ktoś ma inne rozwiązania mógłby się podzielić przykładowym kodem lub algorytmem.
C/C++
#include <SFML/Graphics.hpp>
#include <iostream>

int main()
{
    srand( time( NULL ) );
   
    sf::RenderWindow window( sf::VideoMode( 640, 480 ), "gierka xD" );
    //window.setFramerateLimit(60);
    sf::Clock clock;
   
    // losowa mapa
    sf::RectangleShape rects[ 100 ];
   
    const float qqq = 150.0;
    for( int y = 0; y < 10; ++y ) {
        for( int x = 0; x < 10; ++x ) {
            float px = rand() %( int ) qqq * 10;
            float py = rand() %( int ) qqq * 10;
            rects[ x + y * 10 ].setSize( sf::Vector2f( qqq * 0.5, qqq * 0.5 ) );
            rects[ x + y * 10 ].setPosition( px, py );
            rects[ x + y * 10 ].setFillColor( sf::Color::Green );
        }
    }
   
    // gracz
    sf::CircleShape player( 5.0, 10 );
    player.setFillColor( sf::Color::Black );
    player.setOrigin( sf::Vector2f( player.getRadius(), player.getRadius() ) );
   
    // znajdz wolna pozycje dla gracza.Czasami niedziala;P
    while( 1 ) {
        bool found = false;
        sf::Vector2f pp( rand() %( int ) qqq * 10, rand() %( int ) qqq * 10 );
        player.setPosition( pp );
        for( int q = 0; q < 100; ++q ) {
            sf::RectangleShape rect = rects[ q ];
            sf::FloatRect rbound = rect.getGlobalBounds();
            if( rbound.intersects( player.getGlobalBounds() ) )
                 found = false;
            else
                 found = true;
           
        }
        if( found )
             break;
       
    }
   
    const float dstep = 1.0;
    float dirH, dirV;
   
    while( window.isOpen() )
    {
        sf::Event event;
        while( window.pollEvent( event ) )
        {
            if( event.type == sf::Event::Closed )
                 window.close();
           
        }
       
        dirV = dirH = 0.0;
        if( sf::Keyboard::isKeyPressed( sf::Keyboard::Right ) )
             dirH = dstep;
        else if( sf::Keyboard::isKeyPressed( sf::Keyboard::Left ) )
             dirH = - dstep;
       
        if( sf::Keyboard::isKeyPressed( sf::Keyboard::Up ) )
             dirV = - dstep;
        else if( sf::Keyboard::isKeyPressed( sf::Keyboard::Down ) )
             dirV = dstep;
       
       
        window.clear( sf::Color( 127, 127, 127, 0 ) );
       
        for( int q = 0; q < 100; ++q )
             window.draw( rects[ q ] );
       
        int t = clock.getElapsedTime().asMilliseconds();
        clock.restart();
       
        // stara pozycja gracza bedzie potrzebna pozniej
        sf::Vector2f lastpos( player.getPosition() );
       
        float distance =( 0.2 * t );
        // nowa pozycja dla gracza
        sf::Vector2f plpos( player.getPosition().x +( dirH * distance ), player.getPosition().y +( dirV * distance ) );
       
        //szukanie kolizji.Niedziała przy szybkim ruchu na nowa pozycje
        bool colx = false, coly = false;
        sf::Vector2f forx( plpos.x, lastpos.y ); // stara pozycja z nowym x
        sf::Vector2f fory( lastpos.x, plpos.y ); // stara pozycja z nowym y
        for( int q = 0; q < 100; ++q ) {
            sf::RectangleShape rect = rects[ q ];
            sf::FloatRect rbound = rect.getGlobalBounds();
           
            // try x
            player.setPosition( forx );
            if( rbound.intersects( player.getGlobalBounds() ) )
                 colx = true;
            // try  y
            player.setPosition( fory );
            if( rbound.intersects( player.getGlobalBounds() ) )
                 coly = true;
           
            // jesli na 100% nie bedzie kolidowac z wieloma przerwij
            //if(colx || coly)
            //    break;
           
            // jesli dla x i y jest kolizja niema sensu sprawdzac dalej
            if( colx && coly )
                 break;
           
        }
       
        sf::Vector2f newpos( lastpos );
        if( !colx )
             newpos.x = plpos.x;
       
        if( !coly )
             newpos.y = plpos.y;
       
        player.setPosition( newpos );
       
        sf::View view = window.getDefaultView();
        view.setCenter( player.getPosition() );
        window.setView( view );
       
        window.draw( player );
        window.display();
    }
    return 0;
}
P-71007
Mrovqa
» 2012-12-14 20:23:11
1. Wygodniej jest stworzyć klasę, która obsługuje kolizje.
2. Nie przejmuj się efektem tunnelingu - w dobrych silnikach fizycznych takich jak np. box2d ze względów wydajnościowych (kwantowy czas) też jest ten 'bug'.

@down niewykluczone, jeszcze nie rozpocząłem pisania w tej bibliotece, rzuciłem jedynie okiem na dokumentację ;)
P-71030
DejaVu
» 2012-12-14 20:25:11
@up: mijasz się z prawdą :) Box2D posiada flagę czy obiekt jest 'posciskiem' tj. czy jest to obiekt przemieszczający się bardzo szybko. Ta flaga zapobiega efektowi tunnelingu dla szybkich obiektów.
P-71031
krzyk
Temat założony przez niniejszego użytkownika
» 2012-12-14 21:09:45
@Mrovqa
Klasy będą pózniej,narazie szukam sposobów na kolizję.

Co do tunellingu,wymyśliłem sobie że mogę sprawdzać kolizję lini z objektami gdzie początek to stara pozycja a koniec nowa,wtedy wystarczy znależć pierwsze przecięcie linia/objekt.
P-71043
DejaVu
» 2012-12-14 22:13:25
Osobiście to polecałbym pomęczyć się z nauką jakiejś popularnej biblioteki do obsługi kolizji/fizyki, bądź użyciem jakiegoś istniejącego silnika, jeżeli chcesz tworzyć gry. Sam niejednokrotnie pisałem samodzielnie wykrywanie kolizji w grach oraz fizykę i powiem Ci, że żaden bardziej złożony projekt nie został ukończony, ponieważ po ewentualnym napisaniu silnika, kończyła się motywacja wraz z napływem kolejnych problemów do rozwiązania, a po dłuższej przerwie od projektu zachodzi zjawisko 'a może by tak napisać od nowa? Lepiej niż poprzednio?'. Ponadto dokumentacji w domowych produkcjach zazwyczaj się nie robi, a więc bez dużego doświadczenia w pisaniu kodu w sposób czytelny, napotkasz problem "ale po co mi ta funkcja była? jak z niej korzystać?" i zaczniesz wszystko od nowa.
P-71053
krzyk
Temat założony przez niniejszego użytkownika
» 2012-12-17 11:45:25
@up
"ale po co mi ta funkcja była? jak z niej korzystać?"
To naszczęście już dawno za mną,piszę samodokumentujący się kod a w przypadku niejednoznaczności trzasnę komentarz.
Najgorsze to niedoprecyzowanie wymagań,ach to planowanie a raczej jego brak;P


Przeanalizawałem pare silników (Newton,ODE,Chipmunk),sprawdziłem pare sposobów.
Najodpowiedniejszą wydawała metoda SAT ale ilość kodu była większa niż przy użyciu Box2D.

Heh,przynajmniej dowiedziałem się na jakiej zasadzie działają silniki fizyki,więc to niebył stracony czas.
P-71275
« 1 »
  Strona 1 z 1