SFML community forums

Help => General => Topic started by: Roose Bolton of the Dreadfort on October 23, 2012, 11:00:44 pm

Title: CircleShape & Box2D.
Post by: Roose Bolton of the Dreadfort on October 23, 2012, 11:00:44 pm
Right Here is my circle code
sf::CircleShape circle;
circle.setOrigin(15, 15);
circle.setRadius(SCALE * 0.5f);
circle.setPosition(SCALE * BodyIterator->GetPosition().x, SCALE * BodyIterator->GetPosition().y);
circle.setFillColor(sf::Color::Green);
circle.setRotation(BodyIterator->GetAngle() * 180/b2_pi);
circle.setOutlineColor(sf::Color::Red);
circle.setOutlineThickness(1.0f);
 

and this is my box2d code for assigning a circle..

void CreateCircle(b2World& World, int MouseX, int MouseY)
{
        b2BodyDef BodyDef;
    BodyDef.type = b2_dynamicBody;
        BodyDef.position = b2Vec2(MouseX/SCALE, MouseY/SCALE);
        BodyDef.userData = "Circle"; //Naughty ;)
    b2Body* Body = World.CreateBody(&BodyDef);

        b2CircleShape circle;
        circle.m_radius = 0.5f/SCALE;

        b2FixtureDef FixtureDef;
        FixtureDef.density = 10.0f;
    FixtureDef.friction = 0.4f;
        FixtureDef.restitution = 0.2f;
        FixtureDef.shape = &circle;

        Body->CreateFixture(&FixtureDef);
}  
 

oh and my constant it.

static const float SCALE = 30.f;
 

I have boxes working perfectly, but my circles go into the ground by about 1/3 of the shape.. any ideas why it might be happening?
Title: Re: CircleShape & Box2D.
Post by: FRex on October 23, 2012, 11:13:43 pm
Why is your radius in meters 0.5f/30.f? That's almost too small.
Also origin of your circle should be at .width/2.f and .height/2.f of getLocalBounds.
Title: Re: CircleShape & Box2D.
Post by: FRex on October 23, 2012, 11:20:09 pm
Go get debug draw class from my eduard engine thread in lower post and see where the fixture of circle really is.
http://en.sfml-dev.org/forums/index.php?topic=9071.0
But change pixmeters to 30.f
Title: Re: CircleShape & Box2D.
Post by: Roose Bolton of the Dreadfort on October 23, 2012, 11:33:56 pm
Right doing that now :)

edit: Implemented it but it does not know what 'b2Draw' is? I'm using Box2D_v2.1.2

my includes;

#include <SFML\Graphics.hpp>
#include <Box2D\Box2D.h>
 
Title: Re: CircleShape & Box2D.
Post by: FRex on October 23, 2012, 11:44:45 pm
Try changing it to b2DebugDraw
Also a side note: prefer / to \ in paths.
Title: Re: CircleShape & Box2D.
Post by: Roose Bolton of the Dreadfort on October 23, 2012, 11:48:43 pm
I actually fixed the problem by simple changing 1 line.

circle.m_radius = 15.0f/SCALE;
 

You where right about it being too small haha ;)

Your solution to the debugger worked too - I now have a lovely box2d debugger!!!

Thanks so much mate your help is much appreciated!!
Title: [Solved] Re: CircleShape & Box2D. - Solution Included
Post by: Roose Bolton of the Dreadfort on October 23, 2012, 11:55:06 pm
Full Code below, fully working SFML 2.0 test bed with Box2D. Requires Eduard Engine Debugger also (get it from the link above)

NOTE: Code is not in objects for now - instead uses a hack in 'GetUserData()' to switch drawing between a box or a circle.

Help from veeableful & FRex.

Right click to spawn a wheel, left click to spawn a box. Press Space Bar to create an explosion where you mouse is ;) - hold it down to create a blender!! haha

textures used are both 32x32 pixels in dimention.

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

#include <cstdio>
#include <iostream>

static const float SCALE = 30.f;

void CreateGround(b2World& World, float X, float Y, float angle);
void CreateBox(b2World& World, int MouseX, int MouseY);
void CreateCircle(b2World& World, int MouseX, int MouseY);

int main()
{
    /** Prepare the window */
        sf::RenderWindow Window(sf::VideoMode(1300, 720, 32), "SFML Physics Testing - MPEngine");
    Window.setFramerateLimit(60);

        EEDebugDraw3 debugdraw;
        debugdraw.LinkTarget(Window);

    /** Prepare the world */
    b2Vec2 Gravity(0.f, 8.0f);
    b2World World(Gravity, true);

        //Roof.
        CreateGround(World, 10, 10, 0);
        CreateGround(World, 500, 10, 0);
        CreateGround(World, 1000, 10, 0);
        CreateGround(World, 1300, 10, 0);

        //Ground
        CreateGround(World, 10, 710, 0);
        CreateGround(World, 500, 710, 0);
        CreateGround(World, 1000, 710, 0);
        CreateGround(World, 1300, 710, 0);

        //Right Wall
        CreateGround(World, 10, 720, 1.57079633);
        CreateGround(World, 10, 400, 1.57079633);
        CreateGround(World, 10, 200, 1.57079633);

        //Left Wall
        CreateGround(World, 1290, 720, 1.57079633);
        CreateGround(World, 1290, 400, 1.57079633);
        CreateGround(World, 1290, 200, 1.57079633);

        //Platforms - { now it gets interesting. }
        CreateGround(World, 400, 300, 0);
        CreateGround(World, 900, 600, 1.0);
        CreateGround(World, 10, 10, 0);

        World.SetDebugDraw(&debugdraw);

    /** Prepare textures */
    sf::Texture GroundTexture;
    sf::Texture BoxTexture;
        sf::Texture Wheel;

        Wheel.loadFromFile("wheel.png");
    GroundTexture.loadFromFile("wall.png");
    BoxTexture.loadFromFile("box.png");

        bool ApplyForce = false;

    while (Window.isOpen())
    {
        if (sf::Mouse::isButtonPressed(sf::Mouse::Left))
        {
            int MouseX = sf::Mouse::getPosition(Window).x;
            int MouseY = sf::Mouse::getPosition(Window).y;
            CreateBox(World, MouseX, MouseY);
        }

                if(sf::Mouse::isButtonPressed(sf::Mouse::Right))
                {
                        int MouseX = sf::Mouse::getPosition(Window).x;
            int MouseY = sf::Mouse::getPosition(Window).y;
            CreateCircle(World, MouseX, MouseY);
                }

                if(sf::Keyboard::isKeyPressed(sf::Keyboard::Space))
                {
                        ApplyForce = true;
                }
                else
                {
                        ApplyForce = false;
                }

        World.Step(1/60.f, 8, 3);

        Window.clear(sf::Color::Yellow);
        int BodyCount = 0;
        for (b2Body* BodyIterator = World.GetBodyList(); BodyIterator != 0; BodyIterator = BodyIterator->GetNext())
                {
                        if(ApplyForce)
                                BodyIterator->ApplyForce(b2Vec2(0, 5.0f), b2Vec2(sf::Mouse::getPosition(Window).x, sf::Mouse::getPosition(Window).y));
                       

                        if (BodyIterator->GetType() == b2_dynamicBody && BodyIterator->GetUserData() != "Circle" )
            {
                sf::Sprite Sprite;
                Sprite.setTexture(BoxTexture);
                Sprite.setOrigin(16.f, 16.f);
                Sprite.setPosition(SCALE * BodyIterator->GetPosition().x, SCALE * BodyIterator->GetPosition().y);
                Sprite.setRotation(BodyIterator->GetAngle() * 180/b2_pi);
                Window.draw(Sprite);
                ++BodyCount;
            }

                    else if(BodyIterator->GetUserData() == "Circle" )
                        {
                                sf::Sprite WheelSprite;
                                WheelSprite.setTexture(Wheel);
                                WheelSprite.setOrigin( WheelSprite.getGlobalBounds().width / 2,WheelSprite.getGlobalBounds().height / 2 );
                                WheelSprite.setPosition(BodyIterator->GetPosition().x * SCALE, BodyIterator->GetPosition().y * SCALE);
                                WheelSprite.setRotation(BodyIterator->GetAngle() * 180/b2_pi);
                                Window.draw(WheelSprite);
                                ++BodyCount;
                        }
            else
            {
                sf::Sprite GroundSprite;
                GroundSprite.setTexture(GroundTexture);
                                GroundSprite.setOrigin( GroundSprite.getLocalBounds().width / 2,GroundSprite.getLocalBounds().height / 2 );
                GroundSprite.setPosition(BodyIterator->GetPosition().x * SCALE, BodyIterator->GetPosition().y * SCALE);
                GroundSprite.setRotation(BodyIterator->GetAngle() * 180/b2_pi);
                Window.draw(GroundSprite);
                               
                        }
        }

                //World.DrawDebugData(); //Uncomment for debug drawing
        Window.display();
    }

        return 0;
}

void CreateCircle(b2World& World, int MouseX, int MouseY)
{
        b2BodyDef BodyDef;
    BodyDef.type = b2_dynamicBody;
        BodyDef.position = b2Vec2(MouseX/SCALE, MouseY/SCALE);
        BodyDef.userData = "Circle"; //Naughty ;)
    b2Body* Body = World.CreateBody(&BodyDef);

        b2CircleShape circle;
        circle.m_radius = 15.0f/SCALE;

        b2FixtureDef FixtureDef;
        FixtureDef.density = 2.0f;
    FixtureDef.friction = 2.0f;
        FixtureDef.restitution = 0.5f;

        FixtureDef.shape = &circle;

        Body->CreateFixture(&FixtureDef);
}  

void CreateBox(b2World& World, int MouseX, int MouseY)
{
    b2BodyDef BodyDef;
    BodyDef.position = b2Vec2(MouseX/SCALE, MouseY/SCALE);
    BodyDef.type = b2_dynamicBody;
    b2Body* Body = World.CreateBody(&BodyDef);

    b2PolygonShape Shape;
    Shape.SetAsBox((32.f/2)/SCALE, (32.f/2)/SCALE);
    b2FixtureDef FixtureDef;
    FixtureDef.density = 5.f;
    FixtureDef.friction = 5.0f;
        FixtureDef.restitution = 0.0f;
    FixtureDef.shape = &Shape;
    Body->CreateFixture(&FixtureDef);
}

void CreateGround(b2World& World, float X, float Y, float angle)
{
    b2BodyDef BodyDef;
    BodyDef.position = b2Vec2(X/SCALE, Y/SCALE);
    BodyDef.type = b2_staticBody;
        BodyDef.angle = angle;
    b2Body* Body = World.CreateBody(&BodyDef);

    b2PolygonShape Shape;
    Shape.SetAsBox((500.0f/2)/SCALE, (16.0f/2)/SCALE);
    b2FixtureDef FixtureDef;
    FixtureDef.density = 0.f;
    FixtureDef.shape = &Shape;
    Body->CreateFixture(&FixtureDef);
}
 
Title: Re: CircleShape & Box2D.
Post by: FRex on October 24, 2012, 12:36:02 am
Glad you found it, by too small I meant it borders on 0.1f which is bottom limit and 1.f should be the sweet spot to aim at with your conversion rates (Box2D manual).
Title: Re: CircleShape & Box2D.
Post by: Roose Bolton of the Dreadfort on October 24, 2012, 12:55:56 am
Glad you found it, by too small I meant it borders on 0.1f which is bottom limit and 1.f should be the sweet spot to aim at with your conversion rates (Box2D manual).

You think everything looks okay now? - try running it, I'm 90% its working perfectly!
Title: Re: CircleShape & Box2D.
Post by: FRex on October 24, 2012, 01:20:18 am
I had to change a bit since c-tor in Box2D is different, and had to add that old debug draw to my EE project since I'm to lazy to make new one to just test that. You should poll your events even if you don't use them or window might freeze after a few seconds.
Something is still not right you can see with debug draws on.
Title: Re: CircleShape & Box2D.
Post by: FRex on October 24, 2012, 01:40:40 am
Ok, it works fine, debug draw was wrong because you I didn't
Quote
change pixmeters to 30.f
as I told you in second post. :)

Damn I'm stupid at times...
Title: Re: CircleShape & Box2D.
Post by: Roose Bolton of the Dreadfort on October 24, 2012, 04:19:54 pm
Haha well cheers for the help again! Time to start putting it all together into my Game Engine now that my proof of concept works! :)

I'm going to enjoy throwing rocks at my castles!! haha