How to get collision position in box2d - cocos2d-iphone

What's the best way to get the point of collision in box2d. I'm using it with cocos2d and Objective C, but I imagine the API is similar in other languages. Using the b2ContactListener class will produce b2Contact objects, but I can't find any information on the contact position.

You can use the following code to get the point of collision
b2Body *bodyA = contact->GetFixtureA()->GetBody();
b2Body *bodyB = contact->GetFixtureB()->GetBody();
if ((bodyA->GetFixtureList()->GetFilterData().categoryBits == Categorybits1 || bodyA->GetFixtureList()->GetFilterData().categoryBits == categoryBits2) && (bodyB->GetFixtureList()->GetFilterData().categoryBits == categoryBits2 || bodyB->GetFixtureList()->GetFilterData().categoryBits == Categorybits1))
You can get body positions through this code.....
even i am searching how to get point of collision

try this method
OBJECT1_CATEGORY_BITS = 0x00000001;
OBJECT2_CATEGORY_BITS = 0x00000002;
void MyContactListener::PreSolve(b2Contact *contact, const b2Manifold
*oldManifold)
{
b2Fixture *fixtureA = contact->GetFixtureA();
b2Fixture *fixtureB = contact->GetFixtureB();
b2Filter filterA = fixtureA->GetFilterData();
b2Filter filterB = fixtureB->GetFilterData();
if ((filterB.categoryBits == OBJECT1_CATEGORY_BITS) && (filterA.categoryBits == OBJECT2_CATEGORY_BITS))
{
b2Vec2 normal = contact->GetManifold()->localNormal;
NSLog(#"pointX : %f",normal.x);
NSLog(#"pointY : %f",normal.y);
}
}

Related

C++ Box2D Iterate through vector of bodies and deleting

I have created a game which uses a color coded image to create different bodies/fixtures. So for example if the pixel is red it will get stored into an array as 7 and then the program will create a body called jewel. If there are 10 red pixels, 10 jewels will be created:
else if (array[w][h]==7)
{
b2BodyDef Jewel_BodyDef;
Jewel_BodyDef.position.Set(x, y);
m_collectableJewel = m_world->CreateBody(&Jewel_BodyDef);
b2PolygonShape box;
box.SetAsBox(0.5f, 0.5f);
m_collectableJewelFixture=m_collectableJewel->CreateFixture(&box, 0.0f);
collide.m_jewelFix.push_back(m_collectableJewelFixture);
jewels a;
a.jewel_dim.set(1.0f,1.0f);
a.jewel_pos.set(x,y);
m_jewels.push_back(a);
x+=5.0f;
}
My problem is when calculating the collision between the player and the jewels. The program knows when the player has collided with a jewel. However, I can't get it to delete the fixture. Or rather, it will only delete the last fixture placed, i.e. the last one to be created in the vector. Is there a way to name the fixtures individually? So that then the program can delete the one it has actually collided with, rather than the last one?
edit:
int Collision_with_Player::PickJewel(b2Fixture *player, b2Fixture *foot)
{
int CollisionJewel=0;
std::vector<MyContact>::iterator posi;
for(posi = m_contactListener->m_contacts.begin(); posi != m_contactListener->m_contacts.end(); ++posi)
{
MyContact contact = *posi;
for(std::vector<b2Body*>::iterator iterb = m_jewelBodyVec.begin(); iterb != m_jewelBodyVec.end(); ++iterb)
{
for(std::vector<b2Fixture*>::iterator iter = m_jewelFix.begin(); iter != m_jewelFix.end(); ++iter)
{
if ((contact.fixtureA == player && contact.fixtureB == *iter) ||
(contact.fixtureA ==*iter && contact.fixtureB == player))
{
m_deleteJewels.clear();
std::cout<<"size"<<m_deleteJewels.size()<<std::endl;
CollisionJewel=1;
std::cout<<"Jewel"<<*iter<<std::endl;
deletejewel = *iter;
deletejewelbody= *iterb;
}
else
{
CollisionJewel=0;
}
}
}
}
return CollisionJewel;
}
and in another file
if (collide.PickJewel(m_playerFixture, m_footSensorFixture)==1)
{
collide.deletejewelbody->DestroyFixture(collide.deletejewel);
}

Box2d Cocos2d ContactListener detecting collision

My problem is very simple, but I can't fix it.
I have a radar that is rotating and I have a player that is moving with a Joystick
Well, I just want to detect the collision between the radar and the player. It works perfectly when both are moving but it doesn't when radar is moving and my player is not.
Here you have the code to detect it and how it works:
//moves radar
[self schedule:#selector(loopRadar) interval: 12];
//moves player with joystick
body->SetLinearVelocity(b2Vec2(scaledVelocity.x*dt, scaledVelocity.y*dt));
actor.position = ccp(body->GetPosition().x * PTM_RATIO,
body->GetPosition().y * PTM_RATIO);
// DETECTS COLLISION BETWEEN RADAR AND PLAYER
std::vector<MyContact>::iterator pos;
for(pos = _contactListener->_contacts.begin();
pos != _contactListener->_contacts.end(); ++pos) {
MyContact contact = *pos;
if ((contact.fixtureA == radarBody->GetFixtureList() && contact.fixtureB == body->GetFixtureList()) ||
(contact.fixtureA == body->GetFixtureList() && contact.fixtureB == radarBody->GetFixtureList())) {
//DO SOMETHING LIKE GAME OVER
}
}
//ENDS COLLISION
MycontactListener class:
#import "MyContactListener.h"
MyContactListener::MyContactListener() : _contacts() {
}
MyContactListener::~MyContactListener() {
}
void MyContactListener::BeginContact(b2Contact* contact) {
// We need to copy out the data because the b2Contact passed in
// is reused.
MyContact myContact = { contact->GetFixtureA(), contact->GetFixtureB() };
_contacts.push_back(myContact);
}
void MyContactListener::EndContact(b2Contact* contact) {
MyContact myContact = { contact->GetFixtureA(), contact->GetFixtureB() };
std::vector<MyContact>::iterator pos;
pos = std::find(_contacts.begin(), _contacts.end(), myContact);
if (pos != _contacts.end()) {
_contacts.erase(pos);
}
}
void MyContactListener::PreSolve(b2Contact* contact,
const b2Manifold* oldManifold) {
}
void MyContactListener::PostSolve(b2Contact* contact,
const b2ContactImpulse* impulse) {
}
So, the problem is that when radar goes through the player and player isn't moving, it doesn't detect collision, but when both are moving it works perfectly.
Any tips?
Thank you very much!
Worked adding these lines as "LearnCocos2D" said, setting both bodies awake
body->SetAwake(TRUE);
radarBody->SetAwake(TRUE);
Thank you very much!

Getting EXC_BAD_ACCESS signal received when i tried to get collision detection

I stuck at this position and don't know what went wrong in this,
I have enabled ARC in my project. And i made softBody as follows
Ball.h
B2Body *body[NUM_SEGMENT];
CCSprite *ball;
Ball.mm
ball = [CCSprite spriteWithFile:#"Ball1.2.png"];
ball.tag = 1;
for(int i=0;i<NUM_SEGMENT;i++){
float theta = deltaAngle*i;
float x = radius * cosf(theta);
float y = radius * sinf(theta);
b2Vec2 circlePosition = b2Vec2(x/PTM_RATIO,y/PTM_RATIO);
b2BodyDef bodyDef;
bodyDef.type = b2_dynamicBody;
bodyDef.position = (center + circlePosition);
bodyDef.userData = &ball;
body[i] = world->CreateBody(&bodyDef);
outerBodyFixture[i]=body[i]->CreateFixture(&fixtureDef);
[bodies addObject:[NSValue valueWithPointer:body[i]]];
}
And I have given physics to the tiles as follows,
Tile.h
CCSprite *tile;
Tile.mm
tile = [layer1 tileAt:ccp(i, j)];
tile.tag = 0;
b2BodyDef tileDef;
tileDef.type = b2_staticBody;
tileDef.position.Set((tile.position.x+(tile.contentSize.width/2))/(PTM_RATIO), (tile.position.y + (tile.contentSize.height/2))/PTM_RATIO);
tileDef.userData = &tile;
tileBody = world->CreateBody(&tileDef);
Now i tried to catch collision detection and I have made code which will print the tag number of colliding bodies. The code is as follows,
std::vector<MyContact>::iterator pos;
for (pos=_contactListener->_contacts.begin();
pos != _contactListener->_contacts.end(); ++pos) {
MyContact contact = *pos;
b2Body *bodyA = contact.fixtureA->GetBody();
b2Body *bodyB = contact.fixtureB->GetBody();
if (bodyA->GetUserData() != NULL && bodyB->GetUserData() != NULL) {
At this point Getting ERROR: EXC_BAD_ACCESS
CCSprite *spriteA = (__bridge CCSprite *) bodyA->GetUserData();
At this point Getting ERROR: EXC_BAD_ACCESS
CCSprite *spriteB = (__bridge CCSprite *) bodyB->GetUserData();
printf("contact :%d \n",spriteB.tag);
}
}
Don't Know whats wrong with this code,,Give me some solution for this
Your problem is that you store in userData a pointer to a pointer rather than the pointer itself.
tile is already pointing to a CCSprite instance and &tile points to a pointer to a CCSprite instance making your casting incorrect.
So change it to :
tileDef.userData = tile;

How do I resize a b2CircleShape on cocos2d iPhone with Box2D

I have a 2D physics sandbox with a bunch of circles which resize on contact (the bigger one gets bigger, the smaller one gets smaller). I can resize the sprite fine, and I understand that you can't scale a B2Body - you need to destroy it and recreate it, but I'm not familiar enough with Box2D to do it yet.
Here's what I'm doing to resize the sprites:
std::vector<MyContact>::iterator pos;
for(pos = _contactListener->_contacts.begin();
pos != _contactListener->_contacts.end(); ++pos) {
MyContact contact = *pos;
b2Body *bodyA = contact.fixtureA->GetBody();
b2Body *bodyB = contact.fixtureB->GetBody();
if (bodyA->GetUserData() != NULL && bodyB->GetUserData() != NULL) {
PaintBlob *spriteA = (PaintBlob *) bodyA->GetUserData();
PaintBlob *spriteB = (PaintBlob *) bodyB->GetUserData();
NSLog(#"spriteA: %# is touching spriteB: %#", spriteA, spriteB);
if((spriteA.scale > spriteB.scale) && (spriteB.scale > 0)){
spriteA.scale = spriteA.scale + kSCALE_INCREMENT;
spriteB.scale = spriteB.scale - kSCALE_INCREMENT;
}else if (spriteA.scale >0) {
spriteB.scale = spriteB.scale + kSCALE_INCREMENT;
spriteA.scale = spriteA.scale - kSCALE_INCREMENT;
}
}
}
How do I resize (destroy/recreate) the Box2D body (a b2CircleShape?).
I think this is how you do it in C - from emanueleferonato.com (I am not enlightened enough to understand C):
// if I selected a body...
if (body) {
// I know it's a circle, so I am creating a b2CircleShape variable
var circle:b2CircleShape=body.GetShapeList() as b2CircleShape;
// getting the radius..
var r=circle.GetRadius();
// removing the circle shape from the body
body.DestroyShape(circle);
// creating a new circle shape
var circleDef:b2CircleDef;
circleDef = new b2CircleDef();
// calculating new radius
circleDef.radius=r*0.9;
circleDef.density=1.0;
circleDef.friction=0.5;
circleDef.restitution=0.2;
// attach the shape to the body
body.CreateShape(circleDef);
// determine new body mass
body.SetMassFromShapes();
}
return body;
Hi there you handsome devil.
Here's how:
//Radius is worked out by scale * kBLOBDIAMETER /2
contact.fixtureA->GetShape()->m_radius = (spriteA.scale * kBLOBLDIAMETER / 2) /PTM_RATIO;
contact.fixtureB->GetShape()->m_radius = (spriteB.scale * kBLOBLDIAMETER / 2) /PTM_RATIO;
bodyA->ResetMassData();
bodyB->ResetMassData();

Joint in Box2d with cocos2d

I'm new in box2d and I tried to create joint between two body.
I wrote a joint like
b2RevoluteJointDef jointDef;
jointDef.bodyA=worm_head;
jointDef.bodyB=worm_body;
jointDef.lowerAngle = -0.25f * b2_pi; // -45 degrees
jointDef.upperAngle = 0.25f * b2_pi; // 45 degrees
jointDef.enableLimit=true;
jointDef.maxMotorTorque = 10.0f;
jointDef.motorSpeed = 10.0f;
jointDef.enableMotor = true;
joint=(b2DistanceJoint*)_world->CreateJoint(&jointDef);
but body is not moving when head is moving.
my tick method is
- (void)tick:(ccTime) dt {
//we update the position of the b2body based on the sprite position
for (b2Body* body = _world->GetBodyList(); body != nil; body = body->GetNext())
{
if (body->GetUserData() != NULL) {
CCSprite *spritedata = (CCSprite *)body->GetUserData();
if(spritedata.tag==1)
{
b2Vec2 b2Position = b2Vec2(SCREEN_TO_WORLD(spritedata.position.x),
SCREEN_TO_WORLD(spritedata.position.y));
float32 b2Angle = -1 * CC_DEGREES_TO_RADIANS(spritedata.rotation);
body->SetTransform(b2Position,b2Angle);
}
else {
spritedata.position = ccp(body->GetPosition().x * PTM_RATIO,
body->GetPosition().y * PTM_RATIO);
spritedata.rotation = -1 * CC_RADIANS_TO_DEGREES(body->GetAngle());
}
}
}
}
Why is not moving ? How should I change my code ?
In b2RevoluteJointDef , one body is static body and another is dynamic body. My problem is using two dynamic problem. Now, it solved.