I am creating the physical body in box2d as below , this si my code
b2BodyDef carBodyDef;
carBodyDef.position.Set(x/PTM_RATIO,y/PTM_RATIO);
carBodyDef.type=b2_dynamicBody; b2Body* carBody=physicsWorld->CreateBody(&carBodyDef);
b2CircleShape carShape;
carShape.m_radius=rad/40.0f;
b2FixtureDef carFixture;
carFixture.shape=&carShape;
carFixture.density = 1.0f;
carFixture.friction = 0.0f;
carBody->CreateFixture(&carFixture);
return carBody ;
When am running the app, its getting crash ,
with the below erro
*Assertion failed: (IsLocked() == false), function CreateBody,*in box2d
That's because you are creating your body during execution of Step() function of b2World. You can't create new bodies while this function is executing
Related
I tried to set up a prismatic joint, but I get this error upon run time:
Assertion failed: (IsLocked() == false), function CreateBody, file /Users/Aether/Developer/JFRecode/JFRecode/libs/Box2D/Dynamics/b2World.cpp, line 109.
Here is the code for the screen boundaries since I am using it as bodyB.
CGSize s = [CCDirector sharedDirector].winSize;
//define screen boundaries
// Create edges around the entire screen
b2BodyDef groundBodyDef;
groundBodyDef.position.Set(0,0);
_groundBody = _world->CreateBody(&groundBodyDef);
b2EdgeShape groundBox;
b2FixtureDef groundBoxDef;
groundBoxDef.shape = &groundBox;
groundBox.Set(b2Vec2(0,0), b2Vec2(s.width/PTM_RATIO, 0));
_bottomFixture = _groundBody->CreateFixture(&groundBoxDef);
groundBox.Set(b2Vec2(0,0), b2Vec2(0, s.height/PTM_RATIO));
_groundBody->CreateFixture(&groundBoxDef);
groundBox.Set(b2Vec2(0, s.height/PTM_RATIO), b2Vec2(s.width/PTM_RATIO,
s.height/PTM_RATIO));
_groundBody->CreateFixture(&groundBoxDef);
groundBox.Set(b2Vec2(s.width/PTM_RATIO, s.height/PTM_RATIO),
b2Vec2(s.width/PTM_RATIO, 0));
_groundBody->CreateFixture(&groundBoxDef);
Here is the code for the prismatic joint itself
b2PrismaticJointDef jointDef;
b2Vec2 worldAxis(1.0f,0.0f);
jointDef.collideConnected = true;
jointDef.Initialize(_shipBody,_groundBody,
_shipBody->GetWorldCenter(), worldAxis);
_world->CreateJoint(&jointDef);
isLocked indicates that the physics world is being updated. That means you're running this code during the world step method, likely in or as a result of a contact callback method. Delay executing this code until after the world step.
i am implementing a rope which is hanging from top of the screen , now i have use one dynamic body for creating ropes & i use Revolute joints for joining this all dynamic bodies to create a rope. i successfully created rope , Now when i tried to join my this rope on ground body then it's not getting fixed on it . i guess it's happening because of the dynamic body i used in my rope creation. i am trying to join this with Distance joint , but it's not working, i really stuck with this from couple of weeks .. please help .
ropes:
b2Body* link;
CGSize s = [CCDirector sharedDirector].winSize;
CGFloat linkHeight = 0.24;
CGFloat linkWidth = 0.1;
link = world->CreateBody( &bodyDef );
link->CreateFixture( &fixtureDef );
PhysicsSprite* segmentSprite = [PhysicsSprite spriteWithFile:#"rope_seg_new2.png"];
[self addChild:segmentSprite];
[segmentSprite setPhysicsBody:link];
//set up the common properties of the joint before entering the loop
revoluteJointDef.localAnchorA.Set( 0, linkHeight);
revoluteJointDef.localAnchorB.Set( 0, -linkHeight);
//use same definitions to create multiple bodies
for (int i = 0; i < 10 ; i++) {
newLink = world->CreateBody( &bodyDef );
newLink->CreateFixture( &fixtureDef );
PhysicsSprite* segmentSprite = [PhysicsSprite spriteWithFile:#"rope_seg_new2.png"];
[self addChild:segmentSprite];
[segmentSprite setPhysicsBody:link];
revoluteJointDef.bodyA = link;
revoluteJointDef.bodyB = newLink;
world->CreateJoint( &revoluteJointDef );
link = newLink; //prepare for next iteration
}
joint between GroundBody & Rope:
Distance joint :
b2DistanceJointDef jointDef;
jointDef.Initialize(referencebody, link, referencebody->GetWorldCenter(), link-
>GetWorldCenter());
world->CreateJoint( &jointDef );
here, referencebody : groundbody .. link : rope body
i got answer through Revolute joint ...
b2RevoluteJointDef revoluteJointDef;
revoluteJointDef.bodyA = referenceBody;
revoluteJointDef.bodyB = lastLink;
revoluteJointDef.localAnchorA = startPos;//world coords, because m_groundBody is at (0,0)
revoluteJointDef.localAnchorB.Set(0,0);//center of circle
world->CreateJoint( &revoluteJointDef );
My testing environment:
Xcode 4.6, New cocos2d-x+box2d project
cocos2d-2.1beta3-x-2.1.1
PhysicsEditor 1.0.10
I modified a bit in HelloWorldScene of PhysicsEditor cocos2dx demo to make it simpler, Here are some of my code:
initPhysics
gravity.Set(0.0f, 0.0f);
So that the sprite will not move.
Replace source code inside ccTouchesEnded to:
CCTouch* pTouch = (CCTouch *)touches->anyObject();
CCPoint location = pTouch->locationInView(pTouch->view());
CCPoint convLoc = CCDirector::sharedDirector()->convertToGL(location);
b2Vec2 v = b2Vec2(convLoc.x/PTM_RATIO, convLoc.y/PTM_RATIO);
for (b2Body *b = world->GetBodyList(); b; b = b->GetNext())
{
b2Fixture *f = b->GetFixtureList(); // get the first fixture
CCSprite *sprite =(CCSprite *) b->GetUserData();
if(sprite != NULL)
{
if(f -> TestPoint(v))
{
CCLog("You touched a body %d",sprite->getTag());
}
}
}
The problem is that TestPoint only return true in a very small area (not for whole shape area).
Here is the screenshot:
Can anybody suggest how I debug this problem? Thanks
Updated: showing the generated data from PhysicsEditor
The problem is that you only probe for the first fixture. But complex bodies are made from several. The reason is that
Box2d only allows 8 vertexes per fixture
Box2d can only work with convex shapes
This is why complex shapes are decomposed into a list of polygons.
Iterate over the fixture list instead.
b2Fixture *f = body->GetFixtureList();
while(f)
{
if(f -> TestPoint(v))
{
CCLog("You touched a body %d",sprite->getTag());
}
f = f->GetNext();
}
I'm working on a game in Cocos2d with Box2D. Currently I have a system set up where there are some boundaries. They are for a ball. I want meteors to come in from off the screen and smack the ball.
The boundaries are defined in my init method as follows:
// Define the ground body.
b2BodyDef groundBodyDef;
groundBodyDef.type = b2_staticBody;
groundBodyDef.position.Set(0, 0); // bottom-left corner
// 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;
// bottom
groundBox.SetAsEdge(b2Vec2(0,0), b2Vec2(screenSize.width/PTM_RATIO,0));
groundBody->CreateFixture(&groundBox,0);
// top
groundBox.SetAsEdge(b2Vec2(0,screenSize.height/PTM_RATIO), b2Vec2(screenSize.width/PTM_RATIO,screenSize.height/PTM_RATIO));
groundBody->CreateFixture(&groundBox,0);
// left
groundBox.SetAsEdge(b2Vec2(0,screenSize.height/PTM_RATIO), b2Vec2(0,0));
groundBody->CreateFixture(&groundBox,0);
// right
groundBox.SetAsEdge(b2Vec2(screenSize.width/PTM_RATIO,screenSize.height/PTM_RATIO), b2Vec2(screenSize.width/PTM_RATIO,0));
groundBody->CreateFixture(&groundBox,0);
//Collision filter stuff here. Not working.
b2Filter filter;
filter.groupIndex = -2;
groundBody->GetFixtureList()[0].SetFilterData(filter);
My ball is defined as follows:
//Physics object.
b2BodyDef ballBodyDef;
ballBodyDef.position.Set(ball.position.x/PTM_RATIO, ball.position.y/PTM_RATIO);
ballBodyDef.type = b2_dynamicBody;
ballBodyDef.userData = ball;
ballBodyDef.bullet = true;
ballBody = world->CreateBody(&ballBodyDef);
b2CircleShape ballShape;
ballShape.m_radius = 10.0/PTM_RATIO;
b2FixtureDef ballFix;
ballFix.restitution = 1.1f;
ballFix.density = 0.0f;
ballFix.shape = &ballShape;
ballBody->CreateFixture(&ballFix);
And the meteors are made using two methods, the shorter method places the meteors. The longer one actually creates them using the points given from the shorter one:
-(void)createMeteorAtPoint:(CGPoint)point {
//Create particle sprite representation.
CCParticleMeteor *meteor = [[CCParticleMeteor alloc] initWithTotalParticles:200];
meteor.gravity = ccp(-200,0);
meteor.life = 0.5;
meteor.lifeVar = 0.25;
meteor.position = point;
meteor.tag = 2;
meteor.startSize = 5.0;
meteor.startSizeVar = 3.0;
[self addChild:meteor];
//Make meteor physics body.
b2BodyDef meteorBodyDef;
meteorBodyDef.position.Set(point.x/PTM_RATIO, point.y/PTM_RATIO);
meteorBodyDef.type = b2_dynamicBody;
meteorBodyDef.userData = meteor;
b2Body *meteorBody = world->CreateBody(&meteorBodyDef);
meteorBody->SetBullet(true);
b2CircleShape meteorShape;
meteorShape.m_radius = 7.5/PTM_RATIO;
b2FixtureDef meteorFix;
meteorFix.shape = &meteorShape;
meteorFix.density = 1;
//Give it the same negative group index of the boundaries to prevent collision.
//Not working.
meteorFix.filter.groupIndex = -2;
meteorBody->CreateFixture(&meteorFix);
//Give it a motion.
b2Vec2 F;
F.Set(CCRANDOM_0_1()*2, 0);
meteorBody->SetLinearVelocity(F);
}
//Create a bunch of meteors that will sweep from left to right.
-(void)createMeteors {
for (int i = 0; i < 8*40; i += 20) {
[self createMeteorAtPoint:ccp(-40.0f, i + 2)];
}
NSLog(#"HERE");
}
I can see physics objects pile up on the side of the screen because I have debug flags set up. But one: They are not getting past the boundary despite being the same negative group index. And two: the ball decides it doesn't like the right wall, and goes through it.
If you believe I am missing something crucial please tell me.
Only one of the boundary fixtures is being given the group index of -2 (the bottom). You can loop over all fixtures of a body like this:
for (b2Fixture* f = body->GetFixtureList(); f; f = f->GetNext())
{
//do something with the fixture 'f'
f->SetFilterData(...);
}
I'm not sure why the ball would be ignoring any walls though (unless you are moving it by creating a mouse joint between the ball and the ground body that the walls belong to, and the joint is set to not collide connected bodies... but in that case the ball would ignore all walls, and only while being moved).
in my app the user is able to move or rotate a box2d fixture. The collision detection works fine. But if I set the fixture as a sensor, with the SetSensor(true) method, the collision detection reacts weird.
In the following picture the red rectangle is the sensor, but a collision is also detected if an other fixture collides with the black border.
Image: http://img851.imageshack.us/img851/7292/rect.png
Is it possible that only the red rectangle reacts as a sensor?
BR
I found the help here:
Box2D Forum
I just forgot to check if the contact is touching (with the IsTouching() method)! Now it works fine!!!
b2BodyDef bodyDef;
bodyDef.type = b2_staticBody;
bodyDef.position.Set(position.x/PTM_RATIO, position.y/PTM_RATIO);
bodyDef.userData = NULL;
b2Body *body = _game.world->CreateBody(&bodyDef);
b2PolygonShape dynamicBox;
dynamicBox.SetAsBox(size.x/2/PTM_RATIO, size.y/2/PTM_RATIO);
b2FixtureDef fixtureDef;
fixtureDef.shape = &dynamicBox;
fixtureDef.isSensor = true;
body->CreateFixture(&fixtureDef);
body->SetTransform(body->GetPosition(), rotatingAngle);