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

[SFML + Box2d]Obracanie sprite'a

Ostatnio zmodyfikowano 2014-05-09 18:53
Autor Wiadomość
kubawal
Temat założony przez niniejszego użytkownika
[SFML + Box2d]Obracanie sprite'a
» 2014-02-24 13:05:54
Witam!

Po pewnej przerwie wracam do programowania mojej gry SFML + Box2d i mam funkcję wyświetlającą podane tekstury w pozycjach poszczególnych fixtur ciała:
C/C++
void Body::displayBody( RenderWindow & win, b2Body * b, Texture ** fillTexture )
// fillTexture to tablica wskaźników do textur
// rysuje wszystkie fixtury w *b dla fixtury num wypełniając *fillTexture[num]
// B2toSF() i SFtoB2() przeliczają jednostki między SFML a Box2d
// RDtoDG() pzelicza radiany na stopnie
{
    bool autoInterpolate = true;
   
    int i = 0;
    for( b2Fixture * f = b->GetFixtureList(); f; f = f->GetNext(), i++ )
    {
        b2Shape * sh = f->GetShape();
        b2AABB aabb = f->GetAABB( 0 ); // aabb fixtury
        Transform st = Transform::Identity;
        st.rotate( RDtoDG( b->GetAngle() ), B2toSF( aabb.GetCenter() ) );
       
        if( fillTexture[ i ] && autoInterpolate )
             fillTexture[ i ]->setSmooth( true );
       
        switch( sh->GetType() )
        {
        case b2Shape::e_polygon:
            {
                b2PolygonShape * s = dynamic_cast < b2PolygonShape *>( sh );
                Sprite sp( * fillTexture[ i ], IntRect( 0.0f, 0.0f, B2toSF( aabb.upperBound.x - aabb.lowerBound.x ),
                B2toSF( aabb.upperBound.y - aabb.lowerBound.y ) ) );
               
                sp.setPosition( B2toSF( aabb.lowerBound ) );
                win.draw( sp, st );
                break;
            }
        case b2Shape::e_circle:
            {
                b2CircleShape * s = dynamic_cast < b2CircleShape *>( sh );
                Sprite sp( * fillTexture[ i ], IntRect( 0.0f, 0.0f, B2toSF( aabb.upperBound.x - aabb.lowerBound.x ),
                B2toSF( aabb.upperBound.y - aabb.lowerBound.y ) ) );
               
                sp.setPosition( B2toSF( aabb.lowerBound ) );
                win.draw( sp, st );
                break;
            }
        case b2Shape::e_edge:
            {
                b2EdgeShape * s = dynamic_cast < b2EdgeShape *>( sh );
                VertexArray va( sf::Lines, 2 );
                va[ 0 ].position = B2toSF( b->GetWorldPoint( s->m_vertex1 ) );
                va[ 0 ].color = Color::White;
                va[ 1 ].position = B2toSF( b->GetWorldPoint( s->m_vertex2 ) );
                va[ 1 ].color = Color::White;
               
                win.draw( va );
                break;
            }
        case b2Shape::e_chain:
            {
                b2ChainShape * s = dynamic_cast < b2ChainShape *>( sh );
               
                for( int32 i = 0; i < s->GetChildCount(); ++i )
                {
                    b2EdgeShape edge;
                    s->GetChildEdge( & edge, i );
                    VertexArray va( sf::Lines, 2 );
                    va[ 0 ].position = B2toSF( b->GetWorldPoint( edge.m_vertex1 ) );
                    va[ 0 ].color = Color::White;
                    va[ 1 ].position = B2toSF( b->GetWorldPoint( edge.m_vertex2 ) );
                    va[ 1 ].color = Color::White;
                   
                    win.draw( va );
                }
                break;
            }
        }
    }
}
Problem jest taki, że niby wszystko jest na dobrych miejscach, ale sprite/y zamiast się obracać po prostu rozciągaję się do wielkości aabb.

Jak powinno wyglądać (bez tekstur):
Jak powinno wyglądać (bez tekstur):
Jak wygląda:
Jak wygląda:
P-105183
maly
» 2014-02-24 13:45:05
Jeśli ten
Sprite( sp( * fillTexture[ i ],...
 to
sf::Sprite
 to on zawsze jest prostokątny.

Wrzucę ogólny przykład jak ja to robię z shape-ami.
C/C++
void drawPolygonShape( sf::RenderWindow & window, sf::Texture & tex, b2Body * body )
{
    b2PolygonShape * PolygonShape =( b2PolygonShape * ) body->GetFixtureList()->GetShape();
   
    sf::ConvexShape ConvexShape( PolygonShape->GetVertexCount() );
   
    for( int i = 0; i < PolygonShape->GetVertexCount(); i++ )
    {
        sf::Vector2f v( PolygonShape->GetVertex( i ).x, PolygonShape->GetVertex( i ).y );
        ConvexShape.setPoint( i, v );
    }
   
    ConvexShape.setPosition( body->GetPosition().x, body->GetPosition().y );
    ConvexShape.setRotation( rad2deg( body->GetAngle() ) );
    ConvexShape.setTexture( & tex );
   
    window.draw( ConvexShape );
}
P-105186
kubawal
Temat założony przez niniejszego użytkownika
» 2014-02-24 14:00:58
Też próbowałem ze shape'ami, ale tekstura w środku nich się nie obraca razem z nimi.

to on zawsze jest prostokątny.
No i co z tego? Tak jest elastyczniej, bo mogę sobie zrobić teksturę z przezroczystością która kształtem będzie podobna lub taka sama do fixtury.
P-105187
maly
» 2014-02-24 14:15:38
Też próbowałem ze shape'ami, ale tekstura w środku nich się nie obraca razem z nimi.
Jeśli mówisz o tym Textured shape - texture not rotate (SFML + Box2d) to robiłeś to źle.
P-105188
kubawal
Temat założony przez niniejszego użytkownika
» 2014-02-24 15:00:29
To jaki sposób jest prawidłowy?
P-105192
maly
» 2014-02-24 15:07:21
Cytuje Laurent-a.
Since the rotation is already applied when you create your shape, SFML doesn't know that it is rotated. To have the texture follow the rotation, you would have to rotate the SFML shape. I don't know if it's possible in your context (i.e. if you can access the unrotated points + rotation angle, rather than the final points).

Mój sposób właśnie tak działa.
P-105194
kubawal
Temat założony przez niniejszego użytkownika
» 2014-02-24 17:11:11
No a mi nie :) sam shape się obraca, ale tekstura jest cały czas w tej samej osi.
P-105205
maly
» 2014-02-24 17:20:05
C/C++
#include <SFML/Graphics.hpp>
#include <Box2D/Box2D.h>
#include <cstdio>

float rad2deg( float rad ) { return rad *( 180.0f / b2_pi ); }
float deg2rad( float deg ) { return deg *( b2_pi / 180.0f ); }

b2Body * addShape( b2World & world, const std::vector < b2Vec2 > & vertices, const sf::Vector2f & center );

void drawPolygonShape( sf::RenderWindow & window, sf::Texture & tex, b2Body * body )
{
    b2PolygonShape * PolygonShape =( b2PolygonShape * ) body->GetFixtureList()->GetShape();
   
    sf::ConvexShape ConvexShape( PolygonShape->GetVertexCount() );
   
    for( int i = 0; i < PolygonShape->GetVertexCount(); i++ )
    {
        sf::Vector2f v( PolygonShape->GetVertex( i ).x, PolygonShape->GetVertex( i ).y );
        ConvexShape.setPoint( i, v );
    }
   
    ConvexShape.setPosition( body->GetPosition().x, body->GetPosition().y );
    ConvexShape.setRotation( rad2deg( body->GetAngle() ) );
    ConvexShape.setTexture( & tex );
   
    window.draw( ConvexShape );
}

int main()
{
    sf::RenderWindow Window( sf::VideoMode( 640, 480, 32 ), "Hello b2World" );
    Window.setFramerateLimit( 60 );
   
    b2World World( b2Vec2( 0.f, 0.f ) );
   
    sf::Texture Texture;
    Texture.loadFromFile( "cb.bmp" );
   
    const float size = 90.0f;
    const float ofs = 20.1f;
    std::vector < b2Vec2 > Vertices;
    Vertices.push_back( b2Vec2( - size, - size ) );
    Vertices.push_back( b2Vec2( 0, - size - ofs ) );
    Vertices.push_back( b2Vec2( size, - size ) );
    Vertices.push_back( b2Vec2( size + ofs, 0 ) );
    Vertices.push_back( b2Vec2( size, size ) );
    Vertices.push_back( b2Vec2( 0, size + ofs ) );
    Vertices.push_back( b2Vec2( - size, size ) );
    Vertices.push_back( b2Vec2( - size - ofs, 0 ) );
    b2Body * Actor = addShape( World, Vertices, sf::Vector2f( 640 / 2, 480 / 2 ) );
    Actor->ApplyAngularImpulse( 100000000.0f, true );
   
    //freopen("output.txt","w",stdout);
    //World.Dump();
   
    float r = 0;
    while( Window.isOpen() )
    {
        sf::Event Event;
        while( Window.pollEvent( Event ) )
        {
            if(( Event.type == sf::Event::KeyPressed && Event.key.code == sf::Keyboard::Escape )
            || Event.type == sf::Event::Closed )
                 Window.close();
           
        }
       
        World.Step( 1.f / 60.f, 16, 8 );
       
        Window.clear( sf::Color( 80, 80, 80, 255 ) );
       
        drawPolygonShape( Window, Texture, Actor );
       
        Window.display();
    }
    return 0;
}

b2Body * addShape( b2World & world, const std::vector < b2Vec2 > & vertices,
const sf::Vector2f & center )
{
    std::vector < b2Vec2 > verts = vertices;
   
    b2BodyDef BodyDef;
    BodyDef.position.Set( center.x, center.y );
    BodyDef.type = b2_dynamicBody;
   
    b2PolygonShape PolygonShape;
    PolygonShape.Set( & verts[ 0 ], verts.size() );
   
    b2FixtureDef FixtureDef;
    FixtureDef.density = 1.0;
    FixtureDef.restitution = 0.5;
    FixtureDef.shape = & PolygonShape;
   
    b2Body * Body = world.CreateBody( & BodyDef );
    Body->CreateFixture( & FixtureDef );
   
    return Body;
}
P-105208
« 1 » 2
  Strona 1 z 2 Następna strona