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

Author Topic: SFML and Box2D  (Read 4502 times)

0 Members and 1 Guest are viewing this topic.

realloc()

  • Newbie
  • *
  • Posts: 5
    • View Profile
SFML and Box2D
« 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......
« Last Edit: March 10, 2014, 09:30:56 pm by realloc() »

Lee R

  • Jr. Member
  • **
  • Posts: 86
    • View Profile
Re: SFML and Box2D
« Reply #1 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.

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11032
    • View Profile
    • development blog
    • Email
AW: SFML and Box2D
« Reply #2 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. ;)
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

realloc()

  • Newbie
  • *
  • Posts: 5
    • View Profile
AW: Re: SFML and Box2D
« Reply #3 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()

realloc()

  • Newbie
  • *
  • Posts: 5
    • View Profile
Re: SFML and Box2D
« Reply #4 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?
   

G.

  • Hero Member
  • *****
  • Posts: 1593
    • View Profile
Re: SFML and Box2D
« Reply #5 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)

realloc()

  • Newbie
  • *
  • Posts: 5
    • View Profile
Re: SFML and Box2D
« Reply #6 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 ^^

realloc()

  • Newbie
  • *
  • Posts: 5
    • View Profile
Re: SFML and Box2D
« Reply #7 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

dabbertorres

  • Hero Member
  • *****
  • Posts: 505
    • View Profile
    • website/blog
Re: SFML and Box2D
« Reply #8 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.

 

anything