SFML community forums

Help => Graphics => Topic started by: realloc() on March 09, 2014, 08:52:11 pm

Title: SFML and Box2D
Post by: realloc() on March 09, 2014, 08:52:11 pm
This is my first post here....
-> so "Hi" to everyone :D

I am currently writing a platformer like game, which I want to be playable for two or more persons.
Because I need  good physics for it (Players should be able to push each other into traps etc.) I replaced my own poor physics with Box2D.

Unfortunally it behaves a bit weird, because the Box2D world seems always to be a bit shifted to the rendered world, so that the characters are half in the ground (see image).
Besides that i use a tilemap and the characters are sometimes stuck between two tiles, although they are on the same level....

The function which converts my map object into a b2World looks like this:

Piece #1:
(out of map converter)

Given Variables:

    b2World world;
    std::vector<extendedSprite *> const & tiles; //<- extendedSprite inherits from sf::Sprite
    std::vector<playerClass *> const & players; //<- playerClass inherits from extendedSprite

Code Piece:
   
size_t i;
    extendedSprite * eSpritePtr = NULL;

    //Convert Tiles
    for (i = 0; i < tiles.size(); i++)
    {
        eSpritePtr = tiles.at(i);

        eSpritePtr->b2_init(world, b2_staticBody);
        eSpritePtr->physBody->SetSleepingAllowed(true);
        eSpritePtr->physBody->SetAwake(false);
    }

    //Convert players
    for (i = 0; i < players.size(); i++)
    {
        eSpritePtr = players.at(i);

        eSpritePtr->b2_init(world, b2_dynamicBody);
        eSpritePtr->physBody->SetFixedRotation(true);
    }

Piece #2:
(out of extendedSprite Class)

Given variables:

b2Body * physBody;
float xVelocity; //Of the Sprite
float yVelocity;
 
Code piece:

void extendedSprite::b2_init(b2World & world, b2BodyType bodyType)
{
    b2BodyDef def;
        def.position = SF_B2_Translator::toB2Vector(getPosition()); //"Converts" Pixels to Meters by dividing them by 48
        def.type = bodyType;
        physBody = world.CreateBody(&def);

    b2FixtureDef fixtureDef;
        b2PolygonShape shape;
            shape.SetAsBox( SF_B2_Translator::toMeters(getGlobalBounds().width / 2), SF_B2_Translator::toMeters(getGlobalBounds().height / 2)); //Again pixel to meter conversion

        fixtureDef.density = 70.f;
        fixtureDef.friction = 0.7f;
        fixtureDef.shape = &shape;
        physBody->CreateFixture(&fixtureDef);

    if (bodyType == b2_dynamicBody)
    {
        physBody->SetLinearVelocity(b2Vec2( SF_B2_Translator::toMeters(xVelocity), SF_B2_Translator::toMeters(yVelocity)));
    }
}
 
...
Later i update the player like this:

       
xVelocity = SF_B2_Translator::toPixels(physBody->GetLinearVelocity().x); //"Converts" Meters to Pixels by multiplying by 48
        yVelocity = SF_B2_Translator::toPixels(physBody->GetLinearVelocity().y);

        setPosition( SF_B2_Translator::toSFVector(physBody->GetPosition()));
...
(Hope that wasn't to much code...)

I can't find my mistakes..... Do you have any ideas?

Is Box2D a good choice at all, if i want my game to be playable over network later?

Thanks in advance,
realloc()

P.S. Sry for my bad English......
Title: Re: SFML and Box2D
Post by: Lee R on March 09, 2014, 09:34:18 pm
I believe Box2d used the object's centre of mass as its position. sf::Sprite use the top left corner by default, so you should use sf::Sprite::setOrigin to correct for that.
Title: AW: SFML and Box2D
Post by: eXpl0it3r on March 09, 2014, 09:51:30 pm
As a tip: It will be extremely helpful to have a debug renderer (search the forum for a simple SFML version). That way you'll always know how Box2D sees your objects. ;)
Title: AW: Re: SFML and Box2D
Post by: realloc() on March 09, 2014, 10:50:12 pm
Wow, that was fast! ^^

Thanks a lot,
I will try this tomorrow and report:

I believe Box2d used the object's centre of mass as its position. sf::Sprite use the top left corner by default, so you should use sf::Sprite::setOrigin to correct for that.

realloc()
Title: Re: SFML and Box2D
Post by: realloc() on March 10, 2014, 09:28:53 pm
First of all: Thanks for the DebugDraw idea, it is very useful!

Like suggested, I also tried to use setOrigin() and it corrected the position of the players, unfortunately it had absolute no effect on the tiles (b2_staticBodies), see the images.

I used the following code:

setOrigin(getGlobalBounds().width / 2, getGlobalBounds().height / 2);

Why are the tiles not affected, why are they still shifted ?_?

btw. could it be, that i also have to turn over the y-axis?
   
Title: Re: SFML and Box2D
Post by: G. on March 10, 2014, 09:34:10 pm
Are you sure you're also setting the origins of your tiles? (dumb question yeah but it really looks like you're not)
Title: Re: SFML and Box2D
Post by: realloc() on March 10, 2014, 09:49:51 pm
I added it to the b2_init method, sooooooo.... yes, the Origins of the Tiles should be set, too ^^
Title: Re: SFML and Box2D
Post by: realloc() on March 10, 2014, 11:35:24 pm
Got it fixed with adding this line after setOrigin()  :D !

setPosition(getPosition().x + getGlobalBounds().width / 2, getPosition().y + getGlobalBounds().height / 2);

...but it feels somehow like a "dirty" solution....

Added a picture of the current state
Title: Re: SFML and Box2D
Post by: dabbertorres on March 11, 2014, 12:49:11 am
That's not dirty actually. If you call setPosition BEFORE you call setOrigin, it's going to be placed according to the initial origin. You should be setting the origin before you do any positioning.