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

Author Topic: SFML and Box2d  (Read 8004 times)

0 Members and 1 Guest are viewing this topic.

vicer1234

  • Jr. Member
  • **
  • Posts: 55
    • View Profile
SFML and Box2d
« on: May 03, 2011, 01:15:52 am »
Hi,
How to manage the co-ordinate system of SFML and Box2d??/
When i use the syntax
groundBodyDef.position.Set(100.0f, 50.0f);
and use this position in SFML

sf::Shape::Rectangle(groundBodyDef.position.x, groundBodyDef.position.y, groundBodyDef.position.x + 680, groundBodyDef.position.y - 10, sf::Color(127, 127, 0, 255));


It draws the rectangle at one position and the collision appears in other position.

Any suggestions ....

Walker

  • Full Member
  • ***
  • Posts: 181
    • View Profile
SFML and Box2d
« Reply #1 on: May 03, 2011, 03:38:35 am »
Not really sure what your question is. Might need some more code or you to elaborate further.

However, box2D's positions refer to the centre of the object whereas SFML's refer to the top-left corner by default (you can change it with SetOrigin/SetCenter). I have no idea where your literal constants for the size of the rectangle have come from, again, more code will probably help here, but try and keep it minimal.

How does the collision "appear"? Do you update the position of the rectangle (SetPosition(get some numbers from box2d object); )? I assume you are actually storing this rectangle somewhere.

As a side note, people generally use a scale to go from box2D units to pixels.

vicer1234

  • Jr. Member
  • **
  • Posts: 55
    • View Profile
SFML and Box2d
« Reply #2 on: May 03, 2011, 01:03:58 pm »
If the body is defined using

b2BodyDef groundBodyDef;

groundBodyDef.position.Set(90.0f/RATIO, 15000.0f/RATIO);    
 //RATIO = 30  //1meter = 30 pixels

where the position of the groundBodyDef in pixels will be ( 3.0, 500.0)


then if the b2BodyDef  position is used to draw the sfml::shape::Rectangle like

sf::Shape::Rectangle(groundBodyDef.position.x, groundBodyDef.position.y, groundBodyDef.position.x + 680, groundBodyDef.position.y - 10, sf::Color(127, 127, 0, 255));


is it the right way of drawing ?? where the box2d shape is drawn correctly??

Walker

  • Full Member
  • ***
  • Posts: 181
    • View Profile
SFML and Box2d
« Reply #3 on: May 03, 2011, 03:08:06 pm »
With these figures you're making an sf::Shape::Rectangle at 3, 500 - 683, 480 (pixels). I'm not sure what happens in SFML when a shape's width/height is less than 0. You have literal constants in here, which suggests you aren't getting the size of the rectangle from the box2D body. Also, if you are converting back from box2D metres to pixels at any point (you should be), I think 15000 pixels down from origin on the Y axis is a bit far for most resolutions/window sizes.

The position of groundBodyDef in METRES is (3, 500). In pixels it is (90, 15000).

I don't know what the rest of your code looks like, but provided you are getting a rectangle constructed correctly, you need to be Clear()ing, Draw()ing and Display()ing as well before you will see any visible result.

Calling
Code: [Select]
sf::Shape::Rectangle(groundBodyDef.position.x, groundBodyDef.position.y, groundBodyDef.position.x + 680, groundBodyDef.position.y - 10, sf::Color(127, 127, 0, 255));

Will not draw the shape.

Have you read the box2D manual? Try displaying the "Hello World" example with SFML.

vicer1234

  • Jr. Member
  • **
  • Posts: 55
    • View Profile
SFML and Box2d
« Reply #4 on: May 03, 2011, 03:34:12 pm »
Code: [Select]

#include<SFML\system.hpp>
#include<SFML/Graphics.hpp>
#include<iostream>
#include<SFML/Window.hpp>
//Box2d
#include<Box2D/Box2D.h>

using namespace sf;

b2World* world;
b2BodyDef groundBodyDef;
b2Body* body;
b2BodyDef bodyDef;

void PhysicsInitialse()
{
//B2_NOT_USED(argc);
//B2_NOT_USED(argv);

b2AABB worldAABB;
worldAABB.lowerBound.Set(-3000/30, -3000/30);
worldAABB.upperBound.Set(3000/30, 3000/30);

// Define the gravity vector.
b2Vec2 gravity(0.0f, 0.1f);

// Do we want to let bodies sleep?
bool doSleep = true;

// Construct a world object, which will hold and simulate the rigid bodies.
world = new b2World(gravity, doSleep);

// Define the ground body.

groundBodyDef.position.Set(0.0f/30.0, 15000.0f/30.0);

// Call the body factory which allocates memory for the ground body
// from a pool and creates the ground box shape (also from a pool).
// The body is also added to the world.
b2Body* groundBody = world->CreateBody(&groundBodyDef);

// Define the ground box shape.
b2PolygonShape groundBox;

// The extents are the half-widths of the box.
groundBox.SetAsBox(9000.0f/30.0, 30.0f/30.0);

// Add the ground fixture to the ground body.
groundBody->CreateFixture(&groundBox, 0.0f);

// Define the dynamic body. We set its position and call the body factory.

bodyDef.type = b2_dynamicBody;
bodyDef.position.Set(9000.0f/30.0,50.0f/30.0);
body = world->CreateBody(&bodyDef);

// Define another box shape for our dynamic body.
b2PolygonShape dynamicBox;
dynamicBox.SetAsBox(1.0f, 1.0f);

// Define the dynamic body fixture.
b2FixtureDef fixtureDef;
fixtureDef.shape = &dynamicBox;

// Set the box density to be non-zero, so it will be dynamic.
fixtureDef.density = 1.0f;

// Override the default friction.
fixtureDef.friction = 0.3f;

// Add the shape to the body.
body->CreateFixture(&fixtureDef);

// When the world destructor is called, all bodies and joints are freed. This can
// create orphaned pointers, so be careful about your world management.

std::cout<<world->GetBodyCount()<<std::endl;

}

void UpdatePhysics()
{
// Prepare for simulation. Typically we use a time step of 1/60 of a
// second (60Hz) and 10 iterations. This provides a high quality simulation
// in most game scenarios.
float32 timeStep = 1.0f / 60.0f;
int32 velocityIterations = 6;
int32 positionIterations = 2;
for (int32 i = 0; i < 60; ++i)
{
// Instruct the world to perform a single step of simulation.
// It is generally best to keep the time step and iterations fixed.
world->Step(timeStep, velocityIterations, positionIterations);

// Clear applied body forces. We didn't apply any forces, but you
// should know about this function.
world->ClearForces();

// Now print the position and angle of the body.
b2Vec2 position = body->GetPosition();
float32 angle = body->GetAngle();

printf("%4.2f %4.2f %4.2f\n", position.x, position.y, angle);
}
}

int main()
{
sf::RenderWindow Game(sf::VideoMode(800,600, 32), "BOX 2d");

Game.SetPosition(55, 174);

sf::Event Event;

PhysicsInitialse();
sf::Shape box = sf::Shape::Rectangle(bodyDef.position.x, bodyDef.position.y, bodyDef.position.x + 5, bodyDef.position.y - 10, sf::Color(127, 0, 0, 255));

sf::Shape ground = sf::Shape::Rectangle(groundBodyDef.position.x, groundBodyDef.position.y, groundBodyDef.position.x + 680, groundBodyDef.position.y - 10, sf::Color(127, 127, 0, 255));

std::cout<<world->GetBodyCount()<<std::endl;
printf("%4.2f %4.2f %4.2f\n", bodyDef.position.x, bodyDef.position.y, bodyDef.angle);


while(Game.IsOpened())
{
while(Game.GetEvent(Event))
{
if(Event.Type == sf::Event::Closed)
Game.Close();
}


Game.Clear(sf::Color(100, 149, 237));

//escape key
if(Game.GetInput().IsKeyDown(sf::Key::Escape))
Game.Close();

if(Game.GetInput().IsMouseButtonDown(sf::Mouse::Left))
{
}

Game.Draw(ground);

UpdatePhysics();

b2Vec2 position = body->GetPosition();
box.SetPosition(position.x, position.y);
Game.Draw(box);

Game.Display();
}
std::cout<<world->GetBodyCount()<<std::endl;
return EXIT_SUCCESS;
}


This is the code i am using. If possible please let me know where the logic is going wrong.

panithadrum

  • Sr. Member
  • ****
  • Posts: 304
    • View Profile
    • Skyrpex@Github
    • Email
SFML and Box2d
« Reply #5 on: May 03, 2011, 06:27:17 pm »
Try this SFML implementation of the debug draw. Maybe some header is missing (like <cmath>)... I don't remember!

DebugDraw.h
Code: [Select]

#include <Box2D\Box2D.h>
#include <SFML\Graphics.hpp>

#define PIXELS_METER /*15.f*/35.f

struct b2AABB;

class DebugDraw : public b2DebugDraw
{
sf::RenderTarget &Target;

public:
DebugDraw(sf::RenderTarget &target);
void DrawPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color);
void DrawSolidPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color);
void DrawCircle(const b2Vec2& center, float32 radius, const b2Color& color);
void DrawSolidCircle(const b2Vec2& center, float32 radius, const b2Vec2& axis, const b2Color& color);
void DrawSegment(const b2Vec2& p1, const b2Vec2& p2, const b2Color& color);
void DrawTransform(const b2Transform& xf);
void DrawPoint(const b2Vec2& p, float32 size, const b2Color& color);
void DrawAABB(b2AABB* aabb, const b2Color& color);
};



DebugDraw.cpp
Code: [Select]
#include "DebugDraw.h"

DebugDraw::DebugDraw(sf::RenderTarget &target)
: Target(target)
{
SetFlags(e_shapeBit | e_jointBit | e_centerOfMassBit /*| e_aabbBit*/);
//SetFlags(0xFFFF);
}

void DebugDraw::DrawPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color)
{
sf::Shape Shape;
Shape.SetOutlineWidth(1.f);
for (int32 i = 0; i < vertexCount; ++i)
{
Shape.AddPoint(vertices[i].x*PIXELS_METER, vertices[i].y*PIXELS_METER, sf::Color(128*color.r, 128*color.g, 128*color.b, 128), sf::Color(color.r*255, color.g*255, color.b*255, 128));
}
target.Draw(Shape);
}
void DebugDraw::DrawSolidPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color)
{
sf::Shape Shape;
Shape.SetOutlineWidth(1.f);
for (int32 i = 0; i < vertexCount; ++i)
{
Shape.AddPoint(vertices[i].x*PIXELS_METER, vertices[i].y*PIXELS_METER, sf::Color(128*color.r, 128*color.g, 128*color.b, 128), sf::Color(color.r*255, color.g*255, color.b*255));
}
target.Draw(Shape);
}
void DebugDraw::DrawCircle(const b2Vec2& center, float32 radius, const b2Color& color)
{
sf::Shape Shape = sf::Shape::Circle(center.x*PIXELS_METER, center.y*PIXELS_METER, radius*PIXELS_METER, sf::Color(128*color.r, 128*color.g, 128*color.b, 128), 1.f, sf::Color(color.r*255, color.g*255, color.b*255));
target.Draw(Shape);
}
void DebugDraw::DrawSolidCircle(const b2Vec2& center, float32 radius, const b2Vec2& axis, const b2Color& color)
{
sf::Shape Shape = sf::Shape::Circle(0.f, 0.f, radius*PIXELS_METER, sf::Color(128*color.r, 128*color.g, 128*color.b, 128), 1.f, sf::Color(color.r*255, color.g*255, color.b*255));
Shape.SetPosition(center.x*PIXELS_METER, center.y*PIXELS_METER);
target.Draw(Shape);
}
void DebugDraw::DrawSegment(const b2Vec2& p1, const b2Vec2& p2, const b2Color& color)
{
sf::Shape Line = sf::Shape::Line(p1.x*PIXELS_METER, p1.y*PIXELS_METER, p2.x*PIXELS_METER, p2.y*PIXELS_METER, 1.f, sf::Color(color.r*255, color.g*255, color.b*255));
target.Draw(Line);
}
void DebugDraw::DrawTransform(const b2Transform& xf)
{
//Log("Debug draw: Transform");
//std::cout << "Drawing transform" << std::endl;
/*b2Vec2 p1 = xf.position, p2;
const float32 k_axisScale = 0.4f;
glBegin(GL_LINES);

glColor3f(1.0f, 0.0f, 0.0f);
glVertex2f(p1.x, p1.y);
p2 = p1 + k_axisScale * xf.R.col1;
glVertex2f(p2.x, p2.y);

glColor3f(0.0f, 1.0f, 0.0f);
glVertex2f(p1.x, p1.y);
p2 = p1 + k_axisScale * xf.R.col2;
glVertex2f(p2.x, p2.y);

glEnd();*/
}
void DebugDraw::DrawPoint(const b2Vec2& p, float32 size, const b2Color& color)
{
target.Draw(sf::Shape::Circle(p.x*PIXELS_METER, p.y*PIXELS_METER, size, sf::Color(color.r*255, color.g*255, color.b*255)));
}
void DebugDraw::DrawAABB(b2AABB* aabb, const b2Color& color)
{
target.Draw(sf::Shape::Rectangle(aabb->lowerBound.x*PIXELS_METER, aabb->lowerBound.y*PIXELS_METER, (aabb->lowerBound.x+aabb->upperBound.x)*PIXELS_METER, (aabb->lowerBound.y+aabb->upperBound.y)*PIXELS_METER, sf::Color(color.r*255, color.g*255, color.b*255)));
}

vicer1234

  • Jr. Member
  • **
  • Posts: 55
    • View Profile
SFML and Box2d
« Reply #6 on: May 03, 2011, 11:01:02 pm »
to draw a vertical wall with box2d

is this logic correct

Code: [Select]

b2BodyDef B_wall;

B_wall.position.Set(600.0, 480.0);
wall = Shape::Line(sf::Vector2f(B_wall.position.x, 40.0), sf::Vector2f(B_wall.position.x, 480.0), 2.0, sf::Color(127, 0, 0));
b2Body* B_wallBody = world->CreateBody(&B_wall);
b2PolygonShape B_wallShape;
B_wallShape.SetAsBox(1.0, 300.0);


Is sfml Line placed with respect to the box2d body ????[/code]

Walker

  • Full Member
  • ***
  • Posts: 181
    • View Profile
SFML and Box2d
« Reply #7 on: May 04, 2011, 02:32:50 am »
Using a working debug draw class would be an excellent way to see what is happening and work out if it's your Box2D code or SFML code that has the issue.

Quote from: "vicer1234"
Is sfml Line placed with respect to the box2d body ????[/code]


It's going to place the line exactly where you told it, which is 600, 40 to 600, 480.


In your other example code, what is meant to happen and what does happen?

You still have the ground shape being made with negative figures. The groundBodyDef X position gets set to 0 divided by 30? When you SetPosition() on box in your main loop, you never convert from Box2D metres back to pixels. These are just a few of the simple errors I spotted.

I think you need to take a step back and think about your pixel/metre ratio and the difference between sizes and positions. I would recommend you create your shapes at 0, 0 and use the box2D body sizes (multiplied by RATIO) to give the shapes their height and width. Then set their centre/origin to their centre (width/2, height/2) before finally setting the position from the relevant box2D object.

Roswell_r

  • Newbie
  • *
  • Posts: 12
    • View Profile
SFML and Box2d
« Reply #8 on: May 07, 2011, 02:12:00 am »
depending on what coordinate system you're using with sf::View (im asuming default) then 0,0 is at top left where-as box2d expects bottom left.

in your debug draw class simply negate the Y coordinate for any glVertex commands. this should be what you're after.

if it doesn't fix it then I will post my code that I know works.

 

anything