Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: position with SFML and Box2D  (Read 6756 times)

0 Members and 1 Guest are viewing this topic.

slok

  • Newbie
  • *
  • Posts: 3
    • View Profile
position with SFML and Box2D
« on: February 09, 2010, 09:03:47 am »
Hello! I have problems with the positioning of the SFML and Box2D.

I have read some posts but I don't understand with that information, and now  Box2D has changed a little. I want to know how to render  the SFML shapes or sprites with the Box2D coordinates, the conversion and in general an explanation of that conversion. I'm starting with this two librarys, sorry.

I understand the scale factor and the conversion of Radians, but like  I said before I have problems, the shapes don't act well.
Thank you.

G.

  • Hero Member
  • *****
  • Posts: 1592
    • View Profile
position with SFML and Box2D
« Reply #1 on: February 09, 2010, 11:04:17 pm »
Hi.

I don't know how the latest box2D release works.
All I can say is that in the previous version the center of your box2D shape body is the real center, while the center of your sf::Shape or sf::Sprite is the top left corner.
It may be the source of your incorrect positioning.


Update your physics entities positions. (world->step)
Update your sprites positions.(Box2D units are meters, SFML's are pixels. So there's your conversion, multiply your physics entities positions by your pixel per meter constant to get your new sprites positions)
Render.

slok

  • Newbie
  • *
  • Posts: 3
    • View Profile
position with SFML and Box2D
« Reply #2 on: February 10, 2010, 07:52:51 am »
Thanks for answering, but I think I do it that way and I have problems, well I have to change something. I have to put the center of the SFML shape to the center (to rotate correctly) and the positioning of the shape changes to the center like you said, in the box2D style. Maybe I'm not correctly.
 Well I am playing with a Demo to understand the physics so here is the code (is a demo and isn't well designed, sorry):

Piece.h

Code: [Select]
#ifndef PIECE_H
#define PIECE_H

#include <SFML/Graphics.hpp>
#include <iostream>
#include "Box2D/Box2D.h"
#include "DemoWorld.h"


class Piece
{
    public:

        //Piece();
        Piece(int pX, int pY, int sX, int sY,float rot, float fric, float rest, float dens, sf::Color c, bool dynamic);
        virtual ~Piece();
        void setPostion(int x, int y);
        void updatePos();
        sf::Shape getShape();
        b2Body *getBody();
        void poorDebugging();


    private:

        b2Body *body;
        sf::Shape shape;
        float sizeX, sizeY, posX, posY, rotAngle;

};

#endif // PIECE_H


Piece.cpp

Code: [Select]
#include "Piece.h"


//DemoWorld::SCALE

/*Piece::Piece()
{}*/

Piece::~Piece()
{
    //dtor
}


Piece::Piece(int pX, int pY, int sX, int sY,float rot, float fric, float rest, float dens, sf::Color c, bool dynamic)
{

    float32 angle, positionX, positionY, sizePieceX, sizePieceY;

    //positionX = (pX/DemoWorld::SCALE);
    //positionY = (pY/DemoWorld::SCALE);

    ////////////////problem??/////////////////////////////////////
    positionX = ((pX+sX/2)/DemoWorld::SCALE);
    positionY = ((pY+sY/2)/DemoWorld::SCALE);
    /////////////////////////////////////////////////////////////
    angle = rot * b2_pi / 180.0;
    sizePieceX = (sX/2)/DemoWorld::SCALE;
    sizePieceY = (sY/2)/DemoWorld::SCALE;

    ///physics
    //create body definition (definition of the body, position and those things)
    b2BodyDef pieceBodyDef = b2BodyDef();

    if (dynamic)
        pieceBodyDef.type = b2_dynamicBody; //make the forces affect to the object?

    pieceBodyDef.angle = angle;
    pieceBodyDef.position.Set(positionX,positionY);


    //create the body;
    b2Body *tempBody = DemoWorld::WORLD->CreateBody(&pieceBodyDef);

    //create the shape (create the Shape with a size) for the fixture
    b2PolygonShape pieceShape = b2PolygonShape();
    pieceShape.SetAsBox(sizePieceX, sizePieceY);

    //create fixture definition (denition of the material more or less)
    b2FixtureDef pieceFixtureDef = b2FixtureDef();
    pieceFixtureDef.friction = fric;
    pieceFixtureDef.restitution = rest;
    pieceFixtureDef.density = dens;
    pieceFixtureDef.shape = &pieceShape;

    //create fixture
    tempBody->CreateFixture(&pieceFixtureDef);

    ///graphics
    sf::Shape s =  sf::Shape::Rectangle(0, 0, sX, sY, c);
    //s.SetPosition(pX,pY);
    ////////////////problem??/////////////////////////////////////
    s.SetPosition(pX+sX/2,pY+sY/2);
    /////////////////////////////////////////////////////////////
    s.SetRotation(rot);
    s.SetCenter(sX/2,sY/2);

    ///update object atributes
    body = tempBody;
    shape = s;
    posX = pX;
    posY = pY;
    sizeX = sX;
    sizeY = sY;
    rotAngle = angle;


}
void Piece::setPostion(int x, int y)
{
}
void Piece::updatePos()
{
    /*float32 x = (body->GetPosition().x*DemoWorld::SCALE);
    float32 y = (body->GetPosition().y*DemoWorld::SCALE);*/

    ////////////////problem??/////////////////////////////////////
    float32 x = (body->GetPosition().x*DemoWorld::SCALE)+(sizeX/2);
    float32 y = (body->GetPosition().y*DemoWorld::SCALE)+(sizeY/2);
    //////////////////////////////////////////////////////////////
    float32 r = -(body->GetAngle()*(180/b2_pi));

    shape.SetPosition(x,y);
    shape.SetRotation(r);
    posX = x;
    posY = y;
    rotAngle = r;
}

sf::Shape Piece::getShape()
{
    return this->shape;
}

b2Body *Piece::getBody()
{
    return this->body;
}

void Piece::poorDebugging()
{
    std::cout << "Box2D: [" << this->getBody()->GetPosition().x << "," << this->getBody()->GetPosition().y << "]\n";
    std::cout << "SFML : [" << this->getShape().GetPosition().x << "," << this->getShape().GetPosition().y << "]\n";
    std::cout << "---------------------------------\n";
}


DemoWorld.cpp


Code: [Select]
#include <SFML/Window.hpp>
#include "DemoWorld.h"
#include "Piece.h"

b2World* DemoWorld::WORLD; //the static has to be like a global variable
sf::RenderWindow* DemoWorld::WINDOW;

DemoWorld::DemoWorld()
{
    ///world
     b2Vec2 gravity = b2Vec2(0.0f, 10.0f);
    //Define sleeping objects
    bool ignoreSleeping = true;
    //create the world
    b2World *w =  new b2World(gravity, ignoreSleeping);
    WORLD = w;

    ///window
    sf::RenderWindow *winApp = new sf::RenderWindow(sf::VideoMode(800, 600, 32), "Box2D & SFML demo V2");
    winApp->SetFramerateLimit(60);
    WINDOW = winApp;
}

DemoWorld::~DemoWorld()
{
    //dtor
}

void DemoWorld::run()
{

    Piece floor = Piece(0, 580, 800, 20, 0.0, 0.8, 0.3, 0.7, sf::Color::White, false);
    Piece box = Piece(340, 0, 50, 100, 30, 0.8, 0.7, 0.7, sf::Color::Red, true);
    Piece box2 = Piece(250, 100, 300, 100, 0.0, 0.8, 0.9, 0.7, sf::Color::Blue, true);
    Piece box3 = Piece(0, 0, 100, 100, 0.0, 0.8, 0.7, 0.7, sf::Color::Green, true);

    std::cout << "bodies: " << WORLD->GetBodyCount() << "\n";

    while ( WINDOW->IsOpened())
    {

        WORLD->Step(1.0f/60.0f,10,10);

        // Process events
        sf::Event Event;
        while (WINDOW->GetEvent(Event))
        {
            // Close window : exit
            if (Event.Type == sf::Event::Closed)
                WINDOW->Close();
        }

        //Physics
        WORLD->ClearForces();
        //the floor isn't updated
        box.updatePos();
        box2.updatePos();
        box3.updatePos();

        box.poorDebugging();

        // Display window contents on screen
        WINDOW->Clear();
        WINDOW->Draw(floor.getShape());
        WINDOW->Draw(box.getShape());
        WINDOW->Draw(box2.getShape());
        WINDOW->Draw(box3.getShape());
        WINDOW->Display();
    }
}


That's the code as I said before is a demo.

EDIT: I had a problem in one variable(I have been changing the positioning form so many times that I wrote one variable for updating  Y with an X position xD) but still doesn't work

slok

  • Newbie
  • *
  • Posts: 3
    • View Profile
position with SFML and Box2D
« Reply #3 on: February 10, 2010, 05:12:15 pm »
Ok... I'm stupid xD I think that I solved. I have been the last 3 days crazy with this and I was updating the shape like if box2D give the coordinates in the upper-left corner, and I was changing many parameters, and now I have been thinking and said "but... box2D has the center coordinates and if i have set the center to the sfml  too I don't have to add any offset..."

well, the error was this (the x and y):


Code: [Select]
void Piece::updatePos()
{
    float32 x = (body->GetPosition().x*DemoWorld::SCALE)+(sizeX/2);
    float32 y = (body->GetPosition().y*DemoWorld::SCALE)+(sizeY/2);
    float32 r = -(body->GetAngle()*(180/b2_pi));

    shape.SetPosition(x,y);
    shape.SetRotation(r);
    posX = x;
    posY = y;
    rotAngle = r;
}


correct:

Code: [Select]
void Piece::updatePos()
{
    float32 x = (body->GetPosition().x*DemoWorld::SCALE);
    float32 y = (body->GetPosition().y*DemoWorld::SCALE);
    float32 r = -(body->GetAngle()*(180/b2_pi));

    shape.SetPosition(x,y);
    shape.SetRotation(r);
    posX = x;
    posY = y;
    rotAngle = r;
}


Thank's G. for everything  :D

 

anything