lately I started playing with box2d and tried abstracting it to class
RigidBody::RigidBody() {
}
RigidBody::RigidBody(const RigidBody& other) {
m_fixture = other.m_fixture;
b2BodyDef bodyDef;
bodyDef.position = other.m_body->GetPosition();
bodyDef.type = other.m_body->GetType();
m_body = Runtime::PhysicsWorld.CreateBody(&bodyDef);
b2FixtureDef fixtureDef;
fixtureDef.shape = m_fixture->GetShape();
fixtureDef.density = m_fixture->GetDensity();
fixtureDef.friction = m_fixture->GetFriction();
fixtureDef.restitution = m_fixture->GetRestitution();
fixtureDef.restitutionThreshold = m_fixture->GetRestitutionThreshold();
m_fixture = m_body->CreateFixture(&fixtureDef);
}
RigidBody::RigidBody(sf::Vector2f pos, BodyType type) {
pos /= Constants::PPM;
b2BodyDef bodyDef;
bodyDef.position = pos;
bodyDef.type = (b2BodyType)type;
m_body = Runtime::PhysicsWorld.CreateBody(&bodyDef);
sf::Vector2f size(50.0f, 50.0f);
size /= 2.0f;
size /= Constants::PPM;
b2PolygonShape shape;
shape.SetAsBox(size.x, size.y);
b2FixtureDef fixtureDef;
fixtureDef.shape = &shape;
fixtureDef.density = 1.0f;
fixtureDef.friction = 0.5f;
fixtureDef.restitution = 0.0f;
fixtureDef.restitutionThreshold = 0.5f;
m_body->CreateFixture(&fixtureDef);
}
RigidBody::~RigidBody() {
Runtime::PhysicsWorld.DestroyBody(m_body);
}
but vector is behaving really weird with it i know it's probably becasue of copy constructor or destructor but I can't figure this out
std::vector<hv::RigidBody> m_Bodies;
the problem is with vector erase when I call m_Bodies.erase(m_Bodies.begin()) for some reason it deletes the last objects
m_Bodies.erase(m_Bodies.begin());
And after I call m_Bodies.erase(m_Bodies.begin()) second time I get this
Also it doesn't matter how many objects is in vector if I call m_Bodies.erase(m_Bodies.begin() + 3) it will always delete the last one
*edit corrected question
The problem was I didn't define operator =
resolved it by
RigidBody* RigidBody::operator=(const RigidBody& other) {
if(m_body)
Runtime::PhysicsWorld.DestroyBody(m_body);
m_fixture = other.m_fixture;
b2BodyDef bodyDef;
bodyDef.position = other.m_body->GetPosition();
bodyDef.type = other.m_body->GetType();
m_body = Runtime::PhysicsWorld.CreateBody(&bodyDef);
b2FixtureDef fixtureDef;
fixtureDef.shape = m_fixture->GetShape();
fixtureDef.density = m_fixture->GetDensity();
fixtureDef.friction = m_fixture->GetFriction();
fixtureDef.restitution = m_fixture->GetRestitution();
fixtureDef.restitutionThreshold = m_fixture->GetRestitutionThreshold();
m_fixture = m_body->CreateFixture(&fixtureDef);
return this;
}
Related
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!
In the game I'm trying to make, I have a ball sprite which bounces thanks to box2d. Here's how my current code looks:
-(id)init
{
ball = [CCSprite spriteWithFile:#"ball.png"];
ball.position = ccp(150, winSize.height * 0.78);
[self addChild:ball];
ball.tag = 2;
b2BodyDef ballBodyDef;
ballBodyDef.type = b2_dynamicBody;
ballBodyDef.position.Set(150/PTM_RATIO, 450/PTM_RATIO);
ballBodyDef.userData = ball;
_body = _world->CreateBody(&ballBodyDef);
b2CircleShape circle;
circle.m_radius = 26.0/PTM_RATIO;
b2FixtureDef ballShapeDef;
ballShapeDef.shape = &circle;
ballShapeDef.density = 0.5f;
ballShapeDef.friction = 1.0f;
ballShapeDef.restitution = 1.0f;
_ballFixture = _body->CreateFixture(&ballShapeDef);
b2Vec2 force = b2Vec2(160, 375);
_body->ApplyLinearImpulse(force, ballBodyDef.position);}
- (void)update:(ccTime) dt {
if(_isPaused == FALSE)
{
_world->Step(dt, 10, 10);
for(b2Body *b = _world->GetBodyList(); b; b=b->GetNext()) {
if (b->GetUserData() != NULL) {
CCSprite *sprite = (CCSprite *)b->GetUserData();
if(sprite.tag == 2)
{
sprite.position = ccp(b->GetPosition().x * PTM_RATIO,
b->GetPosition().y * PTM_RATIO);
sprite.rotation = -1 * CC_RADIANS_TO_DEGREES(b->GetAngle());
}
}
}}
Bouncing itself works fine, my problem is there are instances wherein the ball would bounce on a straight line so to speak, either vertically or horizontally continuously which I am trying to avoid. So my question is, how can I make my ball sprite bounce at an angle instead of a straight line so it wouldn't get stuck bouncing infinitely in the same direction?
You could apply a tiny force or gravity change to the body or the world, "randomly" or at equal intervals.
I have two objects...One static and one dynamic (it is a ball). Static object have polygon shape. Sommethimes when I hit the ball, ball passes through static object :(. I have played with density and other properties, but with no success. Do somebody knows how i can make static body to be impenetrable.
Here is my code
// Create ball body
b2BodyDef ballBodyDef;
ballBodyDef.type = b2_dynamicBody;
ballBodyDef.position.Set(110 / 2 / PTM_RATIO, 300 / PTM_RATIO);
ballBodyDef.userData = playerCartoonSprite;
ballBodyDef.bullet = YES;
playerCartoonBody = localWorld->CreateBody(&ballBodyDef);
// Create circle shape
b2CircleShape circle;
circle.m_radius = 10.0 / PTM_RATIO;
// Create shape definition and add to body
b2FixtureDef ballShapeDef;
ballShapeDef.shape = &circle;
ballShapeDef.density = 0.0f;
ballShapeDef.friction = 0.3f;
ballShapeDef.restitution = 1.f;
playerCartoonFixture = playerCartoonBody->CreateFixture(&ballShapeDef);
// static polygon object
b2BodyDef bodyDef;
bodyDef.type = b2_staticBody;
int num = 6;
b2Vec2 verts[] = {
b2Vec2(8.6f / PTM_RATIO, 89.3f / PTM_RATIO),
b2Vec2(5.0f / PTM_RATIO, 81.7f / PTM_RATIO),
b2Vec2(10.5f / PTM_RATIO, 61.9f / PTM_RATIO),
b2Vec2(13.1f / PTM_RATIO, 9.1f / PTM_RATIO),
b2Vec2(17.3f / PTM_RATIO, 9.9f / PTM_RATIO),
b2Vec2(12.7f / PTM_RATIO, 70.6f / PTM_RATIO)
};
b2PolygonShape boxShape;
boxShape.Set(verts, num);
b2FixtureDef fixtureDef;
fixtureDef.shape = &boxShape;
bodyDef.position.Set(teeterSprite.position.x / PTM_RATIO, teeterSprite.position.y / PTM_RATIO);
fixtureDef.shape = &boxShape;
m_bodyA = world->CreateBody( &bodyDef );
m_bodyA->CreateFixture( &fixtureDef );
I think this could be solution for my problem http://www.emanueleferonato.com/2008/12/19/understanding-custom-polygons-in-box2d/
I am trying to test/create a sample game using Cocos2d 2.0 and box2d. I have a bunch of sprites on the screen and when I press the Sprite, I want a body to be automatically attached to that Sprite. I tried to use the TouchesEnd method but it doesn't seem to work.
Can someone push me in the right direction?
Try this way...
-(void)createB2Body
{
b2PolygonShape shape;
float xDist = (sprite.contentSize.width*0.5f)/PTM_RATIO ;
float yDist = (sprite.contentSize.height*0.5f)/PTM_RATIO ;
shape.SetAsBox(xDist, yDist);
b2BodyDef bd;
bd.type = b2_dynamicBody;
bd.userData = sprite;
bd.linearDamping = 0.5f;
bd.angularDamping = 0.5f;
bd.position.Set(self.position.x/PTM_RATIO, self.position.y/PTM_RATIO);
b2FixtureDef fixDef;
fixDef.shape = &shape;
fixDef.density = 1.0f;
fixDef.friction = 0.1f;
fixDef.restitution = 1.0f;
fixDef.isSensor = true;
self.body = self.world->CreateBody(&bd);
self.body->CreateFixture(&fixDef);
}
Only on touch? then use ccTouchesBegan.
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);