Dżem dobry.
Sporo czasu upłynęło od ostatniego wpisu. Może część uzna za wymówkę to co powiem, ale bierzmowanie + nawał pracy skutecznie zniechęcał do jakiejkolwiek pracy nad kodem
. Jednak dzisiaj, w ten przemiły piątkowy wieczór postanowiłem zredagować wpis o Boxie2D i SFMLu. Wiem że wiele osób ma problemy z integracją tych dwóch bibliotek, a zwłaszcza z odmiennymi zasadami panującymi w każdej z nich. Zapraszam do lektury
Metry i piksele
SFML jak i wiele innych (jak nie wszystkich) bibliotek graficznych, używa jako jednostkę odległości piksele. To chyba oczywiste. W Boxie2D sprawa ma się trochę inaczej, ponieważ tutaj używa się metrów. Już mówię dlaczego. Głównym powodem używania takiej miary jest dokładność fizycznych obliczeń. Box2D najlepiej radzi sobie z liczbami z zakresu 0.1-10 ponieważ wtedy obliczenia są najdokładniejsze. A ponieważ nikt nie będzie używał grafik 10×10 pikseli, wprowadzono wspomniane już metry. Wzory na przeliczenie:
- 1 metr = 50 pikseli czyli metry = piksele*0.02
- 1 piksel to 0.02 metra czyli piksele = metry*50
Radiany i stopnie
Sytuacja podobna jak wcześniej: SFML i inne biblioteki graficzne używają najczęściej do obrotów stopni. Natomiast Box2D radianów… dlaczego ? A dlatego że silnikowi łatwiej operować na takiej jednostce (chociaż twórcy mogli się postarać i wprowadzić wewnętrzny przelicznik stopnie->radiany oraz funkcje z argumentami w stopniach). Wzory:
- Stopnie = (180 * radiany / PI)
- Radiany = (PI * stopnie / 180)
Centrum obrazka
SFML jako domyślny środek obrazka uznaje punkt (0,0). Jednak jeżeli podamy takie dane Boxowi2D, dostaniemy w prezencie pokaz, który fizykę ma głęboko gdzieś. Powód jest prosty: Box2D żąda prawdziwego środka obrazka… jeżeli jego długość i szerokość wynosi 64px na 64px to musimy wyznaczyć środek dzieląc obie wartości przez 2. Dopiero taki wynik (32,32) możemy przekazać dalej do naszego silnika fizycznego.
Wielkość
To tak dla formalności tylko. Jeżeli ustawiliśmy centrum w punkcie 32×32, pamiętajmy, by długość i szerokość była liczona od centrum obrazka czyli 32×32 a nie prawdziwe wymiary (64×64)… beznadziejnie wytłumaczone. Na poniższym kodzie będzie to mam nadzieje lepiej widać
Przykład
Teraz, żeby zobaczyć jak wygląda to w praktyce, przedstawię kilka fragmentów kodu. Mają one za zadanie utworzenie sprite’a, stworzenie świata fizycznego, utworzenie ciała i uruchomienie symulacji.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| //Inicjalizacja świata, SFML'owego sprita i Box2d'owego obiektu. Zakładany obrazek ma wymiary 100x100:
b2World* mWorld;
b2AABB worldAABB;
worldAABB.lowerBound.Set( -3000.0f, -3000.0f ); //Wielkość świata
worldAABB.upperBound.Set( 3000.0f, 3000.0f );
mWorld = new b2World(worldAABB,b2Vec2(0,2.0),true); //Tworzenie świata z grawitacją 2
sf::Image* mImage = new sf::Image; //Ładowanie obrazka
mImage->LoadFromFile("Sciezka/do/twojego/obrazka");
sf::Sprite* mSprite = new sf::Sprite(mImage); //Tworzenie sprita
mSprite.setCenter(50,50); //Ustawiamy centrum obrazka (zakładam że obrazek ma wymiary 100x100)
b2BodyDef bodyDef; //Tworzymy obiekt fizyczny Boxa2D
b2Body* body = mWorld->CreateBody(&bodyDef);
b2PolygonDef shapeDef;
shapeDef.SetAsBox(50*0.02f, 50*0.02); //Ustawiamy wielkość obrazka licząc szerokość i wysokość od centrum (przeliczamy piksele na metry, 1 piksel to 0.02 metra)
shapeDef.density = 1.0f;
shapeDef.friction = 0.3f;
b2MassData mass; //Ustawiamy masę
body->CreateShape(&shapeDef);
body->SetMassFromShapes();
///------------------------------------------------------------------------
///Teraz w pętli głównej dajemy coś takiego:
b2Vec2 pos = body->GetPosition(); //Pobieramy pozycję fizycznego obiektu
float rot = body->GetAngle(); //Pobieramy kąt rotacji obiektu
mSprite->SetPosition(pos.x*50,pos.y*50); //Ustawiamy pozycje sprita
mSprite->SetRotation(-(180*rot/PI)); //Ustawiamy rotację sprita (przeliczamy radiany na stopnie)
float32 timeStep = 1.0f / 60.0f;
int32 iterations = 10;
mWorld->Step(timeStep, iterations); //Symulacja świata |
Zakończenie
Tak dobrnęliśmy do końca. Jeśli masz jakieś uwagi lub inne wskazówki godne dodania do tego wpisu, pisz śmiało
Pozdrawiam !