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

SFML + Box2D - uzyskiwanie pozycji ciała

Ostatnio zmodyfikowano 2014-03-18 13:48
Autor Wiadomość
Haaldor
Temat założony przez niniejszego użytkownika
SFML + Box2D - uzyskiwanie pozycji ciała
» 2014-03-15 19:07:32
Witam,
Uczę się używać Box2D, a do graficznej oprawy używam SFMLa.
Jednakże natrafiłem na problem, w którym po prostu nie wiem, co jest źle.

Linijka, w której najprawdopodobniej jest błąd to:
    
sZiemia.setPosition( wymiaryOkna.x / 2 +( ziemia->GetPosition().x * 100 ), wymiaryOkna.y / 2 -( ziemia->GetPosition().y * 100 ) );
gdzie sZiemia to prostokąt SFMLowy reprezentujący statyczny obiekt, a ziemia jest tym statycznym obiektem.
Nie mam pojęcia, co jest źle, ale obiekt dynamiczny spadający na ziemię graficznie zatrzymuje się dokładnie na środku tego obiektu (zamiast na jego górze). Może ktoś wytłumaczyć o co chodzi lub co robię źle?

Jeśli potrzebny to wklejam cały kod:
C/C++
#include <SFML/Graphics.hpp>
#include <box2d/box2d.h>

#define DEGTORAD 0.0174532925199432957f
#define RADTODEG 57.295779513082320876f


using namespace std;
using namespace sf;



int main()
{
    Vector2u wymiaryOkna( 1200, 800 );
    string nazwaOkna = "box2D + SFML test 002";
    sf::RenderWindow app( sf::VideoMode( wymiaryOkna.x, wymiaryOkna.y ), nazwaOkna );
   
    //poczatkowe zmienne
    Vector2u wymiaryZiemi( 1000, 100 );
    unsigned int promien = 20;
   
    //ograniczenie szybkości działania gry
    Clock ograniczenieKlatek;
   
    //ustawianie box2d
    b2Vec2 gravity( 0.0f, - 10.0f );
    b2World world( gravity );
   
    b2BodyDef definicjaCiala;
    definicjaCiala.position.Set( 0, - 1 );
    definicjaCiala.type = b2_staticBody;
   
    b2Body * ziemia = world.CreateBody( & definicjaCiala );
   
    b2PolygonShape groundShape;
    groundShape.SetAsBox( wymiaryZiemi.x / 200, wymiaryZiemi.y / 200 );
    ziemia->CreateFixture( & groundShape, 0 );
   
    definicjaCiala.position.Set( 0, 2 );
    definicjaCiala.type = b2_dynamicBody;
   
    b2Body * cialo = world.CreateBody( & definicjaCiala );
   
    b2CircleShape bodyShape;
    bodyShape.m_p.Set( 0, 0 );
    bodyShape.m_radius = promien / 100;
   
    b2FixtureDef fixtureDef;
    fixtureDef.shape = & bodyShape;
    fixtureDef.density = 1;
    fixtureDef.friction = 0.3;
    fixtureDef.restitution = 0.8;
   
    cialo->CreateFixture( & fixtureDef );
   
    float32 timeStep = 1.0f / 60.0f;
    int32 velocityIterations = 8;
    int32 positionIterations = 3;
   
    //ustawianie sfml
    RectangleShape sZiemia(( Vector2f ) wymiaryZiemi );
    sZiemia.setOrigin( wymiaryZiemi.x / 2, wymiaryZiemi.y / 2 );
    sZiemia.setPosition( wymiaryOkna.x / 2 +( ziemia->GetPosition().x * 100 ), wymiaryOkna.y / 2 -( ziemia->GetPosition().y * 100 ) );
    sZiemia.setFillColor( Color::Black );
   
    CircleShape kolko( promien );
    kolko.setOrigin( promien, promien );
    kolko.setFillColor( Color::Blue );
   
    ziemia->SetTransform( ziemia->GetPosition(), 0 * DEGTORAD );
    sZiemia.setRotation( ziemia->GetAngle() * RADTODEG *( - 1 ) );
   
   
    // Start the game loop
    while( app.isOpen() )
    {
       
        if( ograniczenieKlatek.getElapsedTime().asMilliseconds() <( 100 / 6 ) ) continue;
       
        // Process events
        sf::Event event;
        while( app.pollEvent( event ) )
        {
            // Close window : exit
            if( event.type == sf::Event::Closed )
                 app.close();
           
        }
       
        world.Step( timeStep, velocityIterations, positionIterations );
       
        // Clear screen
        app.clear( Color::White );
       
        kolko.setPosition( wymiaryOkna.x / 2 +( cialo->GetPosition().x * 100 ), wymiaryOkna.y / 2 -( cialo->GetPosition().y * 100 ) );
       
        app.draw( sZiemia );
        app.draw( kolko );
       
        // Update the window
        app.display();
        ograniczenieKlatek.restart();
    }
   
    return 0;
}
P-106473
MrPoxipol
» 2014-03-15 20:40:43
Używaj tych pozycji, które podaje Ci Box, a jak nie będzie działać to znaczy, że coś zepsułeś w ustawieniach świata (kodu nie sprawdzałem).
P-106488
Haaldor
Temat założony przez niniejszego użytkownika
» 2014-03-15 21:40:47
Doszedłem do tego, że to coś z punktem transformacji.
Gdy wywołuję w powyższym programie funkcję SetOrigin używam połowy szerokości i połowy wysokości, by oznaczyć środek danego obiektu (tak, żeby punkty transformacji SFML pokrywały się z tymi z Boxa2D).
Teraz przetestowałem i otrzymałem pożądany wynik dzięki ustawieniu punktu transformacji w SFML dynamicznego ciała na środek dolnej granicy obiektu, a dla statycznego dla górnej. Wiem, że to mało zrozumiałe, ale trudno to zrozumiale opisać :/ Ale jak ktoś chce sobie to wyobrazić, to punkty transformacji stykają się, gdy jedno ciało spadnie na drugie ( a tak nie powinno być)

Stąd wynika moje pytanie: To ja coś źle wpisuję, to jakiś błąd, czy to po prostu mój błędny tok myślenia?

Zmiany w kodzie:

sZiemia.setOrigin( wymiaryZiemi.x / 2, 0 );

zamiast:
sZiemia.setOrigin( wymiaryZiemi.x / 2, wymiaryZiemi.y / 2 );

i
kolko.setOrigin( promien, promien * 2 );

zamiast:
kolko.setOrigin( promien, promien );
P-106499
maly
» 2014-03-18 13:48:55
C/C++
unsigned int promien = 20;
b2CircleShape bodyShape;
bodyShape.m_radius = promien / 100;
m_radius jest równy zero dlatego wydaje Ci się że wpada głębiej niż powinien.

kolko.setPosition( wymiaryOkna.x / 2 +( cialo->GetPosition().x * 100 ), wymiaryOkna.y / 2 -( cialo->GetPosition().y * 100 ) );
Jeśli chcesz coś mieć naśrodko ekranu to albo ustaw pozycję body albo użyj
sf::View
.
P-106687
« 1 »
  Strona 1 z 1