Hello,
I just start to watch SFML and BOX2D adn try to play with those tools. And of course i have some problem ^^
Point 1 : (yes there is more than one point ^^)
I have this function (found on a forum) that work quite fine.
b2Body * CreateBody(b2World *World, b2BodyType type, sf::Shape &Shape, const sf::Vector2f &Position, const sf::Vector2f &Size)
{
// Create the body
b2BodyDef def;
def.type = type;
def.position.Set(Position.x/PIXELS_METER, Position.y/PIXELS_METER);
b2Body* Body = World->CreateBody(&def);
b2PolygonShape pol;
pol.SetAsBox((Size.x)/PIXELS_METER, (Size.y)/PIXELS_METER);
b2FixtureDef fix;
fix.shape = &pol;
fix.density = 1.0f;
fix.friction = 1.3f;
Body->CreateFixture(&fix);
Shape = sf::Shape::Rectangle(0.f, 0.f, Size.x*2, Size.y*2, sf::Color::White);
Shape.SetCenter(Size);
Shape.SetPosition(Position);
return Body;
}
You can see the *2 for creating the shape, I have read that the .setbox take do a *2 of the value that's why we need that.
The problem :
I create my screen with like that :
const int ScreenWidth = 800;
const int ScreenHeight = 600;
...
sf::RenderWindow App(sf::VideoMode(ScreenWidth,ScreenHeight,32), "Main");
...
sf::Shape ground;
b2Body *groundBody = CreateBody(&World, b2_staticBody, ground, sf::Vector2f(ScreenWidth, ScreenHeight), sf::Vector2f(ScreenWidth, 10.f));
...
So you can see that i place ScreenWidth as the width of the object so with the *2 normally I should be able to only place ScreenWidth/2 but if I Place ScreenWidth/2 my "ground" don't take the size of my screen ....
Screen (white bar is the ground):
Point 2:I want to place a sprite (sf::sprite), i create another function exacly the same as the last one
b2Body * CreateBodySpr(b2World *World, b2BodyType type, sf::Sprite &Shape, const sf::Vector2f &Position, const sf::Vector2f &Size)
{
// Create the body
b2BodyDef def;
def.type = type;
def.position.Set(Position.x/PIXELS_METER, Position.y/PIXELS_METER);
b2Body* Body = World->CreateBody(&def);
b2PolygonShape pol;
pol.SetAsBox((Size.x)/(PIXELS_METER), (Size.y)/(PIXELS_METER));
b2FixtureDef fix;
fix.shape = &pol;
fix.density = 1.0f;
fix.friction = 0.3f;
Body->CreateFixture(&fix);
Shape.SetColor(sf::Color::Red);
Shape.SetCenter(Size);
Shape.SetPosition(Position);
return Body;
}
before a prepare my Sprite :
...
sf::Image img = sf::Image();
img.LoadFromFile("data/mario.png");
sf::Sprite mario;
mario.SetImage(img);
b2Body *marioBody = CreateBodySpr(&World, b2_dynamicBody, mario, sf::Vector2f(ScreenWidth, ScreenHeight-50), sf::Vector2f(img.GetWidth(), img.GetHeight()));
...
The problem :
Here my sprite don't touch the other sprite so i think because of the *2 that i can't place here and decide to go on with a /2 and change the line :
pol.SetAsBox((Size.x)/(PIXELS_METER), (Size.y)/(PIXELS_METER));
by
pol.SetAsBox((Size.x/2)/(PIXELS_METER), (Size.y/2)/(PIXELS_METER));
and only with that it was not working finally trying to understand i also change the line
Shape.SetCenter(Size);
by
Shape.SetCenter(Size.x / 2, Size.y / 2);
My problem is that i don't understand why it's working for me it don't make sense ... so if someone can explain to me it should be great
screen before the change :
Point 3:I haven't found explanation regarding the folowing code :
World.SetContinuousPhysics(true);
what it exactly do do i need it
The global Code :
If someone need it here the code i have :
If you have any comment please feel free ^^
#include <iostream>
#include <fstream>
#include <vector>
#include <map>
#include <sfml/Graphics.hpp>
#include <list>
#include <Box2D.h>
using namespace std ;
#define PIXELS_METER 30.f
#define PI 3.1415926
double degreeToRadian(double degree) {
double radian = 0;
radian = degree * (PI/180);
return radian;
}
double radianToDegree(double radian) {
double degree = 0;
degree = radian * (180/PI);
return degree;
}
float RandomFloat(void) {
return (rand() / (float)RAND_MAX);
}
float RandomFloat(float Min,float Max) {
return (RandomFloat() * (Max - Min)) + Min;
}
b2Body * CreateBodySpr(b2World *World, b2BodyType type, sf::Sprite &Shape, const sf::Vector2f &Position, const sf::Vector2f &Size)
{
// Create the body
b2BodyDef def;
def.type = type;
def.position.Set(Position.x/PIXELS_METER, Position.y/PIXELS_METER);
b2Body* Body = World->CreateBody(&def);
b2PolygonShape pol;
pol.SetAsBox((Size.x/2)/(PIXELS_METER), (Size.y/2)/(PIXELS_METER));
b2FixtureDef fix;
fix.shape = &pol;
fix.density = 1.0f;
fix.friction = 0.3f;
Body->CreateFixture(&fix);
Shape.SetColor(sf::Color::Red);
Shape.SetCenter(Size.x / 2, Size.y / 2);
Shape.SetPosition(Position);
return Body;
}
b2Body * CreateBody(b2World *World, b2BodyType type, sf::Shape &Shape, const sf::Vector2f &Position, const sf::Vector2f &Size)
{
// Create the body
b2BodyDef def;
def.type = type;
def.position.Set(Position.x/PIXELS_METER, Position.y/PIXELS_METER);
b2Body* Body = World->CreateBody(&def);
b2PolygonShape pol;
pol.SetAsBox((Size.x)/PIXELS_METER, (Size.y)/PIXELS_METER);
b2FixtureDef fix;
fix.shape = &pol;
fix.density = 1.0f;
fix.friction = 1.3f;
Body->CreateFixture(&fix);
Shape = sf::Shape::Rectangle(0.f, 0.f, Size.x*2, Size.y*2, sf::Color::White);
Shape.SetCenter(Size);
Shape.SetPosition(Position);
return Body;
}
b2Body * CreateBodyR(b2World *World, b2BodyType type, sf::Shape &Shape, const sf::Vector2f &Position, float Radius)
{
// Create the body
b2BodyDef def;
def.type = type;
def.position.Set(Position.x/PIXELS_METER, Position.y/PIXELS_METER);
b2Body* Body = World->CreateBody(&def);
// Creating the box2d circle shape (size in pixels)
b2CircleShape circle;
circle.m_p.Set(Position.x/PIXELS_METER, Position.y/PIXELS_METER);
circle.m_radius = Radius/PIXELS_METER;
b2FixtureDef fix;
fix.shape = &circle;
fix.density = 1.0f;
fix.friction = 0.3f;
Body->CreateFixture(&fix);
Shape = sf::Shape::Circle(Position, Radius, sf::Color::White);
return Body;
}
void Synchronize(b2Body *Body, sf::Drawable &Shape)
{
Shape.SetRotation(-radianToDegree(Body->GetAngle()));
Shape.SetPosition(Body->GetPosition().x*PIXELS_METER, Body->GetPosition().y*PIXELS_METER);
}
class myclass
{
public :
b2Body *physic;
sf::Shape toaff;
int number;
public :
myclass(int x, b2Body *pP, sf::Shape pAff)
{
number = x;
this->physic = pP;
this->toaff = pAff;
}
void myupd()
{
Synchronize(physic, toaff);
}
void mdraw(sf::RenderWindow *App)
{
App->Draw(toaff);
}
~myclass()
{
}
};
typedef list<myclass*> LISTSTR;
//global vars
const int ScreenWidth = 800;
const int ScreenHeight = 600;
const int Speed = 300;
sf::String Text;
typedef void (*pFunc)();
int main()
{
LISTSTR::iterator i;
LISTSTR lstObj;
sf::RenderWindow App(sf::VideoMode(ScreenWidth,ScreenHeight,32), "Main");
bool doSleep = true;
b2Vec2 gravity(0, 9.8f);
int iteration = 10;
float scale = 30;
float timestep = 1 /60;
b2World World( gravity, doSleep);
//World.SetContactListener(collisionManager);
World.SetContinuousPhysics(true);
sf::Shape ground;
b2Body *groundBody = CreateBody(&World, b2_staticBody, ground, sf::Vector2f(ScreenWidth, ScreenHeight), sf::Vector2f(ScreenWidth/2, 10.f));
sf::Image img = sf::Image();
img.LoadFromFile("data/mario.png");
sf::Sprite mario;
cout << "W : " << img.GetWidth() << "\r\n";
cout << "H : " << img.GetHeight() << "\r\n";
mario.SetImage(img);
b2Body *marioBody = CreateBodySpr(&World, b2_dynamicBody, mario, sf::Vector2f(ScreenWidth, ScreenHeight-50), sf::Vector2f(img.GetWidth(), img.GetHeight()));
int count = 0;
while(App.IsOpened())
{
if (count > 1000)
{
float RandomH = RandomFloat(10, 100);
float RandomW = RandomFloat(10, 100);
float RandomY = RandomFloat(0, ScreenHeight-RandomH);
float RandomX = RandomFloat(0, ScreenWidth- RandomW);
sf::Uint8 R = sf::Randomizer::Random(0,255);
sf::Uint8 G = sf::Randomizer::Random(0, 255);
sf::Uint8 B = sf::Randomizer::Random(0, 255);
sf::Uint8 A = sf::Randomizer::Random(10, 250);
A = 255;
float densite = RandomFloat(0, 30);
sf::Shape Shape;
b2Body *Body;
if (sf::Randomizer::Random(0, 10) > 5)
Body = CreateBody(&World, b2_dynamicBody, Shape, sf::Vector2f(RandomX, RandomY), sf::Vector2f(RandomH, RandomW));
else
Body = CreateBodyR(&World, b2_dynamicBody, Shape, sf::Vector2f(RandomX, RandomY), RandomW);
Shape.SetColor(sf::Color(R,G,B,A));
myclass *tmp = new myclass(lstObj.size(), Body, Shape );
lstObj.insert(lstObj.end(), tmp);
count = 0;
}
count++;
World.Step(App.GetFrameTime(), 10, 1);
World.ClearForces();
sf::Event event;
while(App.GetEvent(event))
{
if(event.Type == event.Closed)
App.Close();
}
App.Clear(sf::Color(100,149,237));
if (App.GetInput().IsKeyDown(sf::Key::Escape))
App.Close();
if (App.GetInput().IsKeyDown(sf::Key::Right))
marioBody->SetLinearVelocity(b2Vec2(3,marioBody->GetLinearVelocity().y));
else if (App.GetInput().IsKeyDown(sf::Key::Left))
marioBody->SetLinearVelocity(b2Vec2(-3,marioBody->GetLinearVelocity().y));
else
marioBody->SetLinearVelocity(b2Vec2(0,marioBody->GetLinearVelocity().y));
//faut trouver qq chose ici pour empecher les double saut !!!
if (App.GetInput().IsKeyDown(sf::Key::Up) && marioBody->GetLinearVelocity().y < 1 && marioBody->GetLinearVelocity().y > -1)
marioBody->ApplyLinearImpulse(b2Vec2(0, -9.0f), marioBody->GetWorldCenter());
Synchronize(groundBody, ground);
App.Draw(ground);
Synchronize(marioBody, mario);
App.Draw(mario);
for (i = lstObj.begin(); i != lstObj.end(); ++i)
{
((myclass*)*i)->myupd();
((myclass*)*i)->mdraw(&App);
}
//App.Draw(sprite);
//Window draw
App.Display();
}
return 0;
}
Some screen :
Thanks in advance.