SFML community forums

Help => General => Topic started by: prchakal on May 21, 2013, 11:04:42 pm

Title: Box2D - The physic body is bigger
Post by: prchakal on May 21, 2013, 11:04:42 pm
Hi,

Im using the box2d with sfml and animated sprite class.

You see the example in screenshot attached.

My player is 40/56 (width/height) and when i create the physic body, it is bigger than my sprite size.

If you see in screenshot, you will see that the boxes are one up other, and over the player it have a padding/blank space, the boxes collide with a space bigger than my sprite.

My code:

Quote
void Engine::createPlayerPhysics(b2World& World, int posX, int posY, int width, int height)
{
    b2BodyDef BodyDef;
    BodyDef.position = b2Vec2(posX/SCALE, posY/SCALE);
    BodyDef.type = b2_dynamicBody;
    BodyDef.userData = (void*)"mainPlayer";
    playerBody = World.CreateBody(&BodyDef);

    b2PolygonShape Shape;
    Shape.SetAsBox(width/SCALE, height/SCALE);
    b2FixtureDef FixtureDef;
    FixtureDef.density = 10.f;
    FixtureDef.friction = 0.7f;
    FixtureDef.shape = &Shape;
    playerBody->CreateFixture(&FixtureDef);
}

    ////////////// player ////////////////
    int width = 40;
    int height = 56;

    sf::Texture playerTexture;
    playerTexture.loadFromFile(resourcePath() + "images/player1.png");

    Animation walkingAnimation;
    walkingAnimation.setSpriteSheet(playerTexture);
    walkingAnimation.addFrame(sf::IntRect(0, 2*height, width, height));
    walkingAnimation.addFrame(sf::IntRect(1*width, 2*height, width, height));
    walkingAnimation.addFrame(sf::IntRect(2*width, 2*height, width, height));
    walkingAnimation.addFrame(sf::IntRect(3*width, 2*height, width, height));

    AnimatedSprite animatedSprite(sf::seconds(0.2));
    animatedSprite.setAnimation(walkingAnimation);
   
    createPlayerPhysics(*world, 50, 50, width, height);

What can be wrong?

[attachment deleted by admin]
Title: Re: Box2D - The physic body is bigger
Post by: FRex on May 21, 2013, 11:23:19 pm
SetAsBox takes half width and half height.
Title: Re: Box2D - The physic body is bigger
Post by: prchakal on May 21, 2013, 11:28:51 pm
I change it. But the problems still near the same. See the screenshot attached.

The code:

Quote

void Engine::createPlayerPhysics(b2World& World, int posX, int posY, int width, int height)
{
    b2BodyDef BodyDef;
    BodyDef.position = b2Vec2(posX/SCALE, posY/SCALE);
    BodyDef.type = b2_dynamicBody;
    BodyDef.userData = (void*)"mainPlayer";
    playerBody = World.CreateBody(&BodyDef);

    b2PolygonShape Shape;
    Shape.SetAsBox((width/2)/SCALE, (height/2)/SCALE);
    b2FixtureDef FixtureDef;
    FixtureDef.density = 10.f;
    FixtureDef.friction = 0.7f;
    FixtureDef.shape = &Shape;
    playerBody->CreateFixture(&FixtureDef);
}


My SCALE const is 30.0f;

thanks.

[attachment deleted by admin]
Title: Re: Box2D - The physic body is bigger
Post by: FRex on May 21, 2013, 11:34:51 pm
Bodies in Box2d are positioned by their center and sprites in SFML are positioned by top left corner by default so you need to call setOrigin(width/2.f,height/2.f)
Title: Re: Box2D - The physic body is bigger
Post by: prchakal on May 21, 2013, 11:37:36 pm
I made another test creating a rectangle with AnimatedSprite size and position and it looks ok, only the physic object is wrong.

Attached!

[attachment deleted by admin]
Title: Re: Box2D - The physic body is bigger
Post by: prchakal on May 21, 2013, 11:39:40 pm
FRex very thanks. Is it.

Very nice observation.

Problem solved :)
Title: Re: Box2D - The physic body is bigger
Post by: FRex on May 21, 2013, 11:47:11 pm
For future reference to anyone having Box2D problems:
You should use Box2D debug drawings: http://www.iforce2d.net/b2dtut/debug-draw
There is old code of mine that does that in SFML:
class EEDebugDraw3 : public b2Draw
{
private:
    sf::RenderTarget * m_target;
    //inliners for colour and point conversions
    inline sf::Color EEColor(const b2Color& gCol)
    {
        return sf::Color(static_cast<sf::Uint8>(255*gCol.r),
                        static_cast<sf::Uint8>(255*gCol.g),
                        static_cast<sf::Uint8>(255*gCol.b));
    }
    inline sf::Vector2f EEVector(const b2Vec2& gVec){return sf::Vector2f(gVec.x*pixmeters,gVec.y*pixmeters);}
    const float pixmeters,radegrees;//constants for point and degree conversions
public:
    EEDebugDraw3(void);
    virtual ~EEDebugDraw3(void){};
    void LinkTarget(sf::RenderTarget& gtarget);
    virtual void DrawPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color);
    virtual void DrawSolidPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color);
    virtual void DrawCircle(const b2Vec2& center, float32 radius, const b2Color& color);
    virtual void DrawSolidCircle(const b2Vec2& center, float32 radius, const b2Vec2& axis, const b2Color& color);
    virtual void DrawSegment(const b2Vec2& p1, const b2Vec2& p2, const b2Color& color);
    virtual void DrawTransform(const b2Transform &xf){};
};

#include "EEDebugDraw3.h"
EEDebugDraw3::EEDebugDraw3(void):
pixmeters(32.f),//arbitrary value dependant on the program needs
radegrees(57.2957795f),//degrees per radian,a physical constant
m_target(0x0)
{
    AppendFlags(static_cast<uint32>(~0));//set all drawing bits to 1(not all 32 are relevant but it's ok)
}
void EEDebugDraw3::LinkTarget(sf::RenderTarget& gtarget)
{
    m_target=&gtarget;
}
void EEDebugDraw3::DrawPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color)
{
    sf::ConvexShape shape;
    shape.setOutlineColor(EEColor(color));
    shape.setOutlineThickness(1);
    shape.setFillColor(sf::Color::Transparent);
    shape.setPointCount(vertexCount);
    for(int i=0;i<vertexCount;++i)
    {shape.setPoint(i,EEVector(vertices[i]));}
    m_target->draw(shape);
}
void EEDebugDraw3::DrawSolidPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color)
{
    sf::ConvexShape shape;
    shape.setFillColor(EEColor(color));
    shape.setPointCount(vertexCount);
    for(int i=0;i<vertexCount;++i)
    {shape.setPoint(i,EEVector(vertices[i]));}
    m_target->draw(shape);
}
void EEDebugDraw3::DrawCircle(const b2Vec2& center, float32 radius, const b2Color& color)
{
    sf::CircleShape shape;
    shape.setOutlineColor(EEColor(color));
    shape.setOutlineThickness(1);
    shape.setFillColor(sf::Color::Transparent);
    shape.setRadius(radius*pixmeters);
    shape.setOrigin(sf::Vector2f(radius*pixmeters,radius*pixmeters));//set origin to middle or position setter below would not work correctly
    shape.setPosition(EEVector(center));
    m_target->draw(shape);
}
void EEDebugDraw3::DrawSolidCircle(const b2Vec2& center, float32 radius, const b2Vec2& axis, const b2Color& color)
{
    sf::CircleShape shape;
    shape.setFillColor(EEColor(color));
    shape.setRadius(radius*pixmeters);
    shape.setOrigin(sf::Vector2f(radius*pixmeters,radius*pixmeters));
    shape.setPosition(EEVector(center));
    m_target->draw(shape);
}
void EEDebugDraw3::DrawSegment(const b2Vec2& p1, const b2Vec2& p2, const b2Color& color)
{
    sf::Vertex line[2];//const sized c styled array, safe enough in here
    line[0].color=EEColor(color);
    line[0].position=EEVector(p1);
    line[1].color=EEColor(color);
    line[1].position=EEVector(p2);
    m_target->draw(line,2,sf::Lines);
}
Title: Re: Box2D - The physic body is bigger
Post by: Roose Bolton of the Dreadfort on May 22, 2013, 12:40:19 pm
Yup, using DebugDraw is a must if your implementing Box2D with SFML; I used FRex's code which he posted to me a while ago (same as above) and its works like a charm!
Title: Re: Box2D - The physic body is bigger
Post by: FRex on May 22, 2013, 02:14:54 pm
I'm half happy half scared about that. :P
Also it's missing drawing transforms and someone even sent me a pm about it saying I 'might want to' add it to my class (but I really don't need it for now..) so anyone who misses it might want to add it. ;D