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

[SFML] Ulepszenie kolizji zderzających się kółek

Ostatnio zmodyfikowano 2013-08-31 23:13
Autor Wiadomość
maly
» 2013-08-20 19:19:12
wynikiem tego działanie jest kierunek po odbiciu od powierzchni o podanej normalnej więc nic nie zmieniaj.Po znormalizowaniu go i pomnożeniu przez szybkość lub skok poprostu dodajesz go cały czas do pozycji koła.
P-90644
domin568
Temat założony przez niniejszego użytkownika
» 2013-08-25 23:49:03
SeaMonster napisałeś wcześniej ze arcus tanges (atan2) moge obliczyć kat miedzy tymi punktami , ale za bardzo tego nie rozumiem , bo funkcja ta przyjmuje double x i double y ( chce to jednak sam zrobić , bo przykład małego jest dla mnie nie zrozumiały :D . Czyli jak obliczyć ten kat miedzy 2 punktami z użyciem atan2 ?? Wiem ze zwraca wynik w radianach , ale to już umiem przeliczyć ;)
P-90891
maly
» 2013-08-26 08:54:44
Przykład na podstawie tego co podałem wcześniej, wizualnie wygląda dość poprawnie ale czy z punktu matematyki/fizyki jest dobrze tego nikt niewie;P
C/C++
#include <SFML/Graphics.hpp>
#include <cmath>

sf::Vector2f getKeyCursorDir( float step );

template < typename T >
float distance( const T & v1, const T & v2 )
{
    T t;
    t.x = v1.x - v2.x;
    t.y = v1.y - v2.y;
    return std::sqrt( t.x * t.x + t.y * t.y );
}

template < typename T >
T reflect( const T & dir, const T & normal )
{
    T t;
    t.x = dir.x - 2 * normal.x;
    t.y = dir.y - 2 * normal.y;
    return t;
}

template < typename T >
T normalize( T & v )
{
    float length = v.x * v.x + v.y * v.y;
    if( length )
    {
        length = 1.f / std::sqrt( length );
        v.x = v.x * length;
        v.y = v.y * length;
    }
    return v;
}

bool collideCircleCircle( const sf::Vector2f & positionA, const float radiusA,
const sf::Vector2f & positionB, const float radiusB,
float & depth, sf::Vector2f & normal )
{
    float lp = distance( positionA, positionB );
    float lr = radiusA + radiusB;
   
    if( lp > lr )
         return false;
   
    depth = lr - lp; //std::abs(lp - lr);
    if( depth <= 0.0f )
         return false;
   
    normal = positionA - positionB;
    return true;
}

class Circle
    : public sf::CircleShape
{
public:
    Circle( float radius, const sf::Color & color )
        : sf::CircleShape( radius )
        , Direction( sf::Vector2f() )
    {
        CircleShape::setOrigin( CircleShape::getRadius(), CircleShape::getRadius() );
        CircleShape::setFillColor( color );
    }
   
    void step()
    {
        sf::CircleShape::move( Direction );
    }
    sf::Vector2f Direction;
};

int main()
{
    sf::RenderWindow window( sf::VideoMode( 800, 600 ), "[ SFML Template ]" );
    window.setFramerateLimit( 60 );
   
    Circle CircleA( 50.0f, sf::Color::Blue );
    CircleA.setPosition( 400, 300 + 150 );
   
    Circle CircleB( 50.0f, sf::Color::Green );
    CircleB.setPosition( 400, 300 );
   
    const float step = 2.f;
   
    while( window.isOpen() )
    {
        sf::Event event;
        while( window.pollEvent( event ) )
        {
            if( event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Escape )
                 window.close();
           
        }
       
        // ręczne sterowanie kulą A
        sf::Vector2f newDir = getKeyCursorDir( 1.0f );
        if( newDir.x != 0.0 || newDir.y != 0.0 )
        {
            normalize( newDir );
            newDir *= step;
            CircleA.Direction = newDir;
        }
       
       
        float depth;
        sf::Vector2f normal;
       
        if( collideCircleCircle( CircleA.getPosition(), CircleA.getRadius(), CircleB.getPosition(), CircleB.getRadius(), depth, normal ) )
        {
            // wycofanie kuli A o głębokość na którą wpadły w siebie
            normalize( normal );
            normal *= depth;
            CircleA.move( normal );
           
            #if 1       // 0 bez odbicia
            {
                // nowy kierunek dla kuli A
                //sf::Vector2f refl = sf::Vector2f(CircleA.Direction.x-2*-normal.x, CircleA.Direction.y-2*-normal.y);
                sf::Vector2f refl = reflect( CircleA.Direction, - normal );
                CircleA.Direction = normalize( refl ) * step;;
            }
            {
                // nowy kierunek dla kuli B
                sf::Vector2f refl = reflect( CircleB.Direction, normal );
                CircleB.Direction = normalize( refl ) * step;
            }
            #endif
        }
       
        CircleA.step();
        CircleB.step();
       
        window.clear();
        window.draw( CircleA );
        window.draw( CircleB );
        window.display();
    }
    return 0;
}

sf::Vector2f getKeyCursorDir( float step )
{
    sf::Vector2f dir( 0.0, 0.0 );
    if( sf::Keyboard::isKeyPressed( sf::Keyboard::Up ) )
         dir.y -= step;
   
    if( sf::Keyboard::isKeyPressed( sf::Keyboard::Down ) )
         dir.y += step;
   
    if( sf::Keyboard::isKeyPressed( sf::Keyboard::Left ) )
         dir.x -= step;
   
    if( sf::Keyboard::isKeyPressed( sf::Keyboard::Right ) )
         dir.x += step;
   
    return dir;
}
P-90895
RazzorFlame
» 2013-08-26 15:29:38
Proste użycie atan2:
C/C++
sf::Vector2i posA, posB; //niech przyjmują odpowiednie pozycje dla 2 obiektow
int kat = atan2( posB.y - posA.y, posB.x - posA.x ) * 180 / M_PI;
if( kolizja(...) == true )
{
    //odbicie
    sprajt.move( - cos(( kat * M_PI ) / 180 ) * velocity, - sin(( kat * M_PI ) / 180 ) * velocity );
   
}
Aha i velocity to prędkość.
P-90944
domin568
Temat założony przez niniejszego użytkownika
» 2013-08-28 22:54:14
Przekonwertowałem Twój kod na moje potrzeby
C/C++
int kat = atan2( gracztab[ 0 ].gracz.getPosition().y - gracztab[ 1 ].graczGetPosition().y, gracztab[ 1 ].gracz.getPosition().x - gracztab[ 0 ].gracz.getPosition().x ) * 180 / M_PI;

if( kolizja == true )
{
    gracztab[ 0 ].gracz.move( - cos(( kat * M_PI ) / 180 ) * gracztab[ 0 ].getPredkosc(), - sin(( kat * M_PI ) / 180 ) * gracztab[ 0 ].getPredkosc() );
}

Kąt oblicza się dobrze , ale z samą kolizją jest źle , bo jeżeli najadę na gracza np. z prawej górnej strony to pozwala przejechać . Również jeżeli kulki są na pełnej prędkości to przejadą się przez siebie . Za bardzo nie rozumiem kodu , może to jest problem , jakbyś mógł objaśnić jak to mniejwięcej działa , bo poprostu wklepałem kod bez zastanowienia .
P-91156
domin568
Temat założony przez niniejszego użytkownika
» 2013-08-31 10:48:35
<< Removed by DejaVu - tu się tematów nie odświeża bez powodu. >>
P-91316
DejaVu
» 2013-08-31 23:13:08
Temat zamykam - wiele rozwiązań padło w temacie.
P-91353
1 2 3 « 4 »
Poprzednia strona Strona 4 z 4