When the gravity is very small, the dynamic object will not move after moving for a short distance. When I run this method, the result is The change of dynamic body' position. When the dynamic body moves to a certain position, it will stop. I do not know why. Maybe the precision problem of floating number?
This is the method I run.
void initializeWorld()
{
// Define the gravity vector.
b2Vec2 gravity(0.0f, 0.011f);
// Construct a world object, which will hold and simulate the rigid bodies.
b2World world(gravity);
// Define the up ground body.
b2BodyDef groundBodyDefUp;
groundBodyDefUp.position.Set(0.0f, 8.0f);
// Define the down ground body.
b2BodyDef groundBodyDefDown;
groundBodyDefDown.position.Set(0.0f, -8.0f);
// Define the left ground body
b2BodyDef groundBodyDefLeft;
groundBodyDefLeft.position.Set(-8.0f,0.0f);
// Define the right ground body
b2BodyDef groundBodyDefRight;
groundBodyDefRight.position.Set(8.0f, 0.0f);
// 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* groundBodyUp = world.CreateBody(&groundBodyDefUp);
b2Body* groundBodyDown = world.CreateBody(&groundBodyDefDown);
b2Body* groundBodyLeft = world.CreateBody(&groundBodyDefLeft);
b2Body* groundBodyRight = world.CreateBody(&groundBodyDefRight);
// Define the ground box shape.
b2PolygonShape groundBoxUp;
// The extents are the half-widths of the box.
groundBoxUp.SetAsBox(5.0f, 3.0f);
// Define the ground box shape.
b2PolygonShape groundBoxDown;
// The extents are the half-widths of the box.
groundBoxDown.SetAsBox(5.0f, 3.0f); // Define the ground box shape.
// Define the ground box shape.
b2PolygonShape groundBoxLeft;
// The extents are the half-widths of the box.
groundBoxLeft.SetAsBox(3.0f, 5.0f); // Define the ground box shape.
// Define the ground box shape.
b2PolygonShape groundBoxRight;
// The extents are the half-widths of the box.
groundBoxRight.SetAsBox(3.0f, 5.0f); // Define the ground box shape.
// Add the ground fixture to the ground body.
groundBodyUp->CreateFixture(&groundBoxUp, 0.0f);
/*groundBodyDown->CreateFixture(&groundBoxDown, 0.0f);
groundBodyLeft->CreateFixture(&groundBoxLeft, 0.0f);
groundBodyRight->CreateFixture(&groundBoxRight, 0.0f);*/
// Define the dynamic body. We set its position and call the body factory.
b2BodyDef bodyDef;
bodyDef.type = b2_dynamicBody;
bodyDef.position.Set(0.0f, 0.0f);
b2Body* body = world.CreateBody(&bodyDef);
// Define another box shape for our dynamic body.
b2PolygonShape dynamicBox;
dynamicBox.SetAsBox(0.5f, 0.5f);
// 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);
// 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;
bool running = true;
while (running)
{
world.Step(timeStep, velocityIterations, positionIterations);
b2Vec2 position = body->GetPosition();
cout << "(" << position.x << "," << position.y <<")"<< endl;
}
}
Related
i am getting back to box2d after many years of absence and thought to start from zero. on top of that decided to work with the C++ version this time (in the past worked with the Javascript version)
For a reason the very first program described in box2d.org does not run properly. When i compile it i do not get any errors however the result is wrong.
The result is 0.00 4.00 0.00 and remains as such.
But with each iteration of timestep, the position.y should decrease (position.x and angle should remain the same)
#include "include/box2d/box2d.h"
#include <iostream>
#include <stdio.h>
int main(){
b2Vec2 gravity(0.0f, -10.0f); // define the gravity vector
b2World world(gravity); //create the world object
//Creating static Ground Body
b2BodyDef groundBodyDef; //body definition
groundBodyDef.position.Set(0.0f, -10.0f);
b2Body* groundBody = world.CreateBody(&groundBodyDef); // body definition is passed to the world object to create the ground body
b2PolygonShape groundBox; //create a ground polygon.
groundBox.SetAsBox(50.0f, 10.0f); //We use the SetAsBox shortcut to form the ground polygon into a box shape
groundBody->CreateFixture(&groundBox, 0.0f); //creating the shape fixture
//Creating Dynamic Body
b2BodyDef bodyDef;
bodyDef.type = b2_dynamicBody; //By default bodies are static, so we should set the b2BodyType at construction time to make the body dynamic
bodyDef.position.Set(0.0f, 4.0f);
b2Body* body = world.CreateBody(&bodyDef);
b2PolygonShape dynamicBox; //create a box shap
dynamicBox.SetAsBox(1.0f, 1.0f);
//A dynamic body should have at least one fixture with a non-zero density. Otherwise you will get strange behavior.
b2FixtureDef fixtureDef; // fixture definition using the box
fixtureDef.shape = &dynamicBox;
fixtureDef.density = 1.0f;
fixtureDef.friction = 0.3f;
float timeStep = 1.0f / 60.0f; //Integrators simulate the physics equations at discrete points of time -> ie timeStep
int32 velocityIterations = 6;
int32 positionIterations = 2;
for (int32 i = 0; i < 60; ++i) {
world.Step(timeStep, velocityIterations, positionIterations);
b2Vec2 position = body->GetPosition();
float angle = body->GetAngle();
printf("%4.2f %4.2f %4.2f\n", position.x, position.y, angle);
}
//return 0;
}
Apologies for the noobie question, but cannot find my mistake. i almost copy paste everything!
I actually forgot to include body->CreateFixture(&fixtureDef);
I am trying to detect a collision between a static body and a kinematic body using the b2ContactListener class but my code is not detecting a collision between my two fixtures. I placed an EdgeShape at the top of my kinematic body and made it a fixture to detect a collision with my static body fixture. I am using SFML to draw to the screen and detect keyboard events.
Here is my main function:
int main()
{
Vector2f resolution;
resolution.x = VideoMode::getDesktopMode().width;
resolution.y = VideoMode::getDesktopMode().height;
RenderWindow window(VideoMode(resolution.x, resolution.y),
"Box2D Test", Style::Fullscreen);
Vector2f staticRectSize(100.0f, 20.0f);
Vector2f kinematicRectSize(40.0f, 20.0f);
Event keyBoardEvent;
b2Vec2 gravity(0.0f, 0.0f);
b2World world(gravity);
// Creating static body and fixture
b2BodyDef groundBodyDef;
groundBodyDef.position.Set(100.0f, 150.0f);
b2Body* groundBody = world.CreateBody(&groundBodyDef);
b2PolygonShape groundBox;
groundBox.SetAsBox(50.0f, 10.0f);
groundBody->CreateFixture(&groundBox, 0.0f);
// Creating kinematic body and fixture
b2BodyDef bodyDef;
bodyDef.type = b2_kinematicBody;
bodyDef.position.Set(125.0f, 700.0f);
b2Body* body = world.CreateBody(&bodyDef);
b2PolygonShape kinematicBox;
kinematicBox.SetAsBox(20.0f, 10.0f);
b2FixtureDef fixtureDef;
fixtureDef.shape = &kinematicBox;
fixtureDef.density = 1.0f;
fixtureDef.friction = 0.3f;
body->CreateFixture(&fixtureDef);
// world.Step inputs
float32 timeStep = 1.0f / 60.0f;
int32 velocityIterations = 6;
int32 positionIterations = 2;
RectangleShape staticRect(staticRectSize);
RectangleShape dynamicRect(kinematicRectSize);
b2Vec2 staticPosition = groundBody->GetPosition();
staticRect.setPosition(staticPosition.x, staticPosition.y);
b2Vec2 dynamicPosition = body->GetPosition();
// Creating EdgeShape
b2EdgeShape top;
top.Set(b2Vec2(dynamicPosition.x, dynamicPosition.y), b2Vec2(dynamicPosition.x + 40.0, dynamicPosition.y));
fixtureDef.shape = ⊤
fixtureDef.isSensor = true;
body->CreateFixture(&fixtureDef)->SetUserData("top collision");
// Creating an instance of myContactListener class
myContactListener contactListener;
world.SetContactListener(&contactListener);
while (window.isOpen())
{
world.Step(timeStep, velocityIterations, positionIterations);
dynamicPosition = body->GetPosition();
dynamicRect.setPosition(dynamicPosition.x, dynamicPosition.y);
while (window.pollEvent(keyBoardEvent))
{
if (keyBoardEvent.type == Event::KeyPressed)
{
if (keyBoardEvent.key.code == Keyboard::W)
{
body->SetLinearVelocity(b2Vec2(0, -10));
}
...
window.clear();
window.draw(staticRect);
window.draw(dynamicRect);
window.draw(line);
window.display();
if (Keyboard::isKeyPressed(Keyboard::Escape))
{
break;
}
}
return 0;
}
And here is my MyContactListiner.cpp:
void myContactListener::BeginContact(b2Contact* contact)
{
b2Fixture *fa = contact->GetFixtureA();
b2Fixture *fb = contact->GetFixtureB();
if (fa == NULL || fb == NULL) { return; }
while (1)
{
printf("Collision occurred");
if (Keyboard::isKeyPressed(Keyboard::Escape))
{
break;
}
}
}
Box2D doesn't do collision handling for static bodies directly against other static or kinematic bodies. They're both theoretically of infinite mass for which laws of motion don't seem to make much sense anymore (at least not to me in terms of collisions).
Probably easiest to make the kinematic body a dynamic one instead.
You could alternatively surround one of the bodies with dynamic ones to get the contact listener to fire up. The dynamic bodies can't be made to drive the kinematic or static one it surrounds however in the substep phases without more effort than I think it'd be worth.
Hope this answer helps!
I'm creating a triangle shaped polygon in Box2D (C++) using this code:
b2FixtureDef fixtureDef;
b2PolygonShape dynamicPolygon;
b2Vec2 vertices[3];
vertices[0].Set(0, -1);
vertices[1].Set(-1, 1);
vertices[2].Set(1, 1);
dynamicPolygon.Set(vertices, 3);
fixtureDef.shape = &dynamicPolygon;
However, upon running this code, I get this error:
a.out: ./Box2D/Collision/Shapes/b2PolygonShape.cpp:127: b2Vec2 ComputeCentroid(const b2Vec2*, int32): Assertion `area > 1.19209289550781250000e-7F' failed.
The area seems to be too small, however, the points should make a correct triangle?
Any ideas?
I needed to swap the values of vertices 1 and 2:
b2FixtureDef fixtureDef;
b2PolygonShape dynamicPolygon;
b2Vec2 vertices[3];
vertices[0].Set(0, -1);
vertices[1].Set(1, 1);
vertices[2].Set(-1, 1);
dynamicPolygon.Set(vertices, 3);
fixtureDef.shape = &dynamicPolygon;
This option puts the vertices in counter-clockwise order works...
I have a problem with Box2d. I created an object (circle) in the center of the screen that rotates to see if I set Box2d well, following the tutorial that I found on internet. The problem is that the circle is created, but I can't rotate despite I followed exactly the tutorial found on internet. This is the code:
file .h:
b2World * _world;
GLESDebugDraw * _debugDraw;
file .mm:
-(void)setupWorld {
b2Vec2 gravity = b2Vec2(0.0f, 0.0f);
bool doSleep = false;
_world = new b2World(gravity, doSleep);
}
-(void)setupDebugDraw {
_debugDraw = new GLESDebugDraw(PTM_RATIO*[[CCDirector sharedDirector] contentScaleFactor]);
_world->SetDebugDraw(_debugDraw);
_debugDraw->SetFlags(b2DebugDraw::e_shapeBit |b2DebugDraw::e_jointBit);
}
-(void)testBox2D {
CGSize winSize = [CCDirector sharedDirector].winSize;
b2BodyDef bodyDef;
bodyDef.type = b2_dynamicBody;
bodyDef.position = b2Vec2(winSize.width/2/PTM_RATIO,winSize.height/2/PTM_RATIO);
b2Body *body = _world->CreateBody(&bodyDef);
b2CircleShape circleShape;
circleShape.m_radius = 25.0/PTM_RATIO;
b2FixtureDef fixtureDef;
fixtureDef.shape = &circleShape;
fixtureDef.density = 1.0;
body->CreateFixture(&fixtureDef);
body->ApplyAngularImpulse(0.01);
}
-(void)updateBox2D:(ccTime)dt {
_world->Step(dt, 1, 1);
[self updateBox2D:dt];
}
-(void) draw {
glDisable(GL_TEXTURE_2D); glDisableClientState(GL_COLOR_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY);
_world->DrawDebugData();
glEnable(GL_TEXTURE_2D); glEnableClientState(GL_COLOR_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY);
}

in init:
[self setupWorld];
[self setupDebugDraw];
[self testBox2D];
Two problems:
Are you recursively calling updateBox2D? This looks like an infinite loop to me, and I'm surprised that it's not crashing your application.
Instead, you should only call your world's step once (or a few times depending on how you've setup your time step) during your CCScene tick method.
Your next problem is that you're applying a small impulse to your body, but it is only a one-time impulse... Angular impulses are still affected by damping, so the body will not rotate indefinitely by default. To keep your body rotating, you need to set the angular damping to zero:
bodyDef.angularDamping = 0.0f;
Can you help. Want to draw a polygon (beams at different angles) and apply box 2d body to it. Can you please let me know how to create a CCSprite with a polygon shape
Any examples would help
Cheers
Create Polygon body.
-(void) createDynamicPoly {
b2BodyDef bodyDefPoly;
bodyDefPoly.type = b2_dynamicBody;
bodyDefPoly.position.Set(3.0f, 10.0f);
b2Body *polyBody = world->CreateBody(&bodyDefPoly);
int count = 8;
b2Vec2 vertices[8];
vertices[0].Set(0.0f / PTM_RATIO,0.0f / PTM_RATIO);
vertices[1].Set(48.0f/PTM_RATIO,0.0f/PTM_RATIO);
vertices[2].Set(48.0f/PTM_RATIO,30.0f/PTM_RATIO);
vertices[3].Set(42.0f/PTM_RATIO,30.0f/PTM_RATIO);
vertices[4].Set(30.0f/PTM_RATIO,18.0f/PTM_RATIO);
vertices[5].Set(18.0f/PTM_RATIO,12.0f/PTM_RATIO);
vertices[6].Set(6.0f/PTM_RATIO,18.0f/PTM_RATIO);
vertices[7].Set(0.0f/PTM_RATIO,30.0f/PTM_RATIO);
b2PolygonShape polygon;
polygon.Set(vertices, count);
b2FixtureDef fixtureDefPoly;
fixtureDefPoly.shape = &polygon;
fixtureDefPoly.density = 1.0f;
fixtureDefPoly.friction = 0.3f;
polyBody->CreateFixture(&fixtureDefPoly);
}
Create your sprite
Attach your sprite to the Polygon body via Fixture and UserData
fixtureDefPoly.SetUserData() = spriteObject;
b2Fixture *fixture;
fixture = circleBody->CreateFixture(&fixtureDefPoly);
fixture->SetUserData(#"spriteObject");
Then Iterate the sprite to the body in your update method.
The easiest way is to open an image editor (such as paint for example or photoshop) and create the image you want. The use it in your program.
Also there is a helloWorld scene when creating an xcode application using cocos2d box2d template. It creates a set of squares with a texture.
CGPoint startPt = edge.start ;
CGPoint endpt = edge.end ;
//length of the stick body
float len = abs(ccpDistance(startPt, endpt))/PTM_RATIO;
//to calculate the angle and position of the body.
float dx = endpt.x-startPt.x;
float dy = endpt.y-startPt.y;
//position of the body
float xPos = startPt.x+dx/2.0f;
float yPos = startPt.y+dy/2.0f;
//width of the body.
float width = 1.0f/PTM_RATIO;
b2BodyDef bodyDef;
bodyDef.position.Set(xPos/PTM_RATIO, yPos/PTM_RATIO);
bodyDef.angle = atan(dy/dx);
NSLog([NSString stringWithFormat:#"Setting angle %f",bodyDef.angle]);
CCSprite *sp = [CCSprite spriteWithFile:#"material-wood.png" rect:CGRectMake(0, 0, 12, 12)];
//TODO: fix shape
[self addChild:sp z:1 ];
bodyDef.userData = sp;
bodyDef.type = b2_dynamicBody;
b2Body* body = world->CreateBody(&bodyDef);
b2PolygonShape shape;
b2Vec2 rectangle1_vertices[4];
rectangle1_vertices[0].Set(-len/2, -width/2);
rectangle1_vertices[1].Set(len/2, -width/2);
rectangle1_vertices[2].Set(len/2, width/2);
rectangle1_vertices[3].Set(-len/2, width/2);
shape.Set(rectangle1_vertices, 4);
b2FixtureDef fd;
fd.shape = &shape;
fd.density = 1.0f;
fd.friction = 0.300000f;
fd.restitution = 0.600000f;
body->CreateFixture(&fd);