Collision 2 object in box2d

I have two objects : GameObject* A & GameObject* B, each objet have two animation:idle and colli, with each animation, object have state: m_stateidle and m_statecolli .

i want one condition : “When object A in m_statecolli and object B in m_stateidle OR object A in m_statedile and object B in m_statecolli”, two object collide each other

i use ContactListerner.h vs ContactListerner.cpp

class ContactListener : public b2ContactListener {
public:
    ContactListener();
    ~ContactListener();

    virtual void BeginContact(b2Contact *contact);
    virtual void EndContact(b2Contact *contact);
    virtual void PreSolve(b2Contact *contact, const b2Manifold *oldManifold);
    virtual void PostSolve(b2Contact *contact, const b2ContactImpulse *impulse);
};

ContactListener::ContactListener() {
}

ContactListener::~ContactListener() {
}

void ContactListener::BeginContact(b2Contact *contact) {

    }
}

void ContactListener::EndContact(b2Contact *contact) {

    }
}

void ContactListener::PreSolve(b2Contact *contact, const b2Manifold *oldManifold) {
}

void ContactListener::PostSolve(b2Contact *contact, const b2ContactImpulse *impulse) {
}

so how to two object collide with condition. thanks

You can do something like this in your contact listener

void ContactListener::BeginContact(b2Contact* contact) {
    if (contact->IsTouching()) {
        b2Fixture *a = contact->GetFixtureA();
        b2Fixture *b = contact->GetFixtureB();
        b2Body *aBody = a->GetBody();
        b2Body *bBody = b->GetBody();

        if (aBody !=NULL && bBody != NULL) {
            GameObject *obj = static_cast(aBody->GetUserData());
            GameObject *obj2 = static_cast(bBody->GetUserData());

            if(obj != NULL && obj2 != NULL) {
                obj->collisionCallback(obj2);
                obj2->collisionCallback(obj);
            }
        }

    }
}

And in your GameObject Class create a function like this
void collisionCallback(GameObject *obj);

So whenever your collision happens both objects get a callback to collisionCallback with the other object…

can’t detect detect collsion in box2d, RootObject inherit from CCNode:

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* bodyAUserData = contact->GetFixtureA()->GetBody()->GetUserData();
    void* bodyBUserData = contact->GetFixtureB()->GetBody()->GetUserData();


    if(bodyAUserData!=NULL && bodyBUserData!=NULL)
    {
        RootObject* obj = static_cast(bodyAUserData);
        RootObject* obj1 = static_cast(bodyBUserData);

       obj->collisioncallBack(obj1);
       obj1->collisioncallBack(obj);


    }

}

class RootObject()
{
     void RootObject :: collisioncallBack(RootObject *obj)
     {
        m_actionState = kActionIdle ;
         if(obj->m_actionState == kActionIdle)// this condition can't check although it's true:(
        {
           obj->m_actionState = kActionBigger; //i add breakpoint here and can't run this 

        }
    else if(this->m_actionState == kActionIdle)
      {
        this->m_actionState = kActionBigger;
      }
    }
}

In RootObject class, m_actionState init : kActionIdle. So why can’t run this line added breakpoint:(, i think it’s out of gameloop? so can’t check . I have 5 ball (RootObject in scene)

use CCLog to check if it is going in the callback function.

Also have you added an object of ContactListener class in your box2d world.

world->SetContactListener(&ContactListenerInstance);

yeah, i added u added an object of ContactListener class in your box2d world,
as i said,
if(obj->m_actionState == kActionIdle) can’t check although it’s true:(

try adding a CCLog in your contact listener.

void RootObject :: collisioncallBack(RootObject *obj)
     {
        CCLog("object action state %d", obj->m_actionState);
        m_actionState = kActionIdle ;
         if(obj->m_actionState == kActionIdle)// this condition can't check although it's true:(
        {
           obj->m_actionState = kActionBigger; //i add breakpoint here and can't run this 

        }
    else if(this->m_actionState == kActionIdle)
      {
        this->m_actionState = kActionBigger;
      }
    }

So object action state : 2 >_< ,

my code :

enum ActionState
{
   kActionIdle =1,
   kActionBigger,
   kActionCollision,
};

try this instead

CCLog("object action state %d", (int)obj->m_actionState);

if it still gives garbage value, that means the enum object isn’t getting set.

when two ball collsion , ball actionState gives garbage value_, but i add cclog in init method, it give true result(1), so why_

Can you paste your entire class here… it would be easier to debug.

//
//  RootObject.cpp
//  GameBlastar
//
//  Created by Lion User on 04/03/2013.
//
//

#include "RootObject.h"
#include "Global.h"


RootObject::RootObject(b2World *m_world,CCLayer*layer,CCPoint position,b2Vec2 force )
{
    cache = CCSpriteFrameCache::sharedSpriteFrameCache();
    cache->addSpriteFramesWithFile("Blue_1.plist");


    m_Layer = layer;
    world = m_world ;
    m_score = 0;
    m_force = force;

    m_Collision = false;
    m_Bigger = false;
    m_actionState = kActionIdle ; // init ball is action idle
    CCLOG("init state : %d",(int)m_actionState);




    spritebatch = CCSpriteBatchNode::create("Blue_1.pvr");
    m_pSprite1 = CCSprite::createWithSpriteFrameName("Blue_1.png");
    m_pSprite1->setPosition(CCPoint(position));


    spritebatch->addChild(m_pSprite1);


    m_Layer->addChild(spritebatch);


    arrayAction = CCArray ::createWithCapacity(3);
    arrayAction->retain();

    CCArray *idleAnimFrames = CCArray::createWithCapacity(10);
    idleAnimFrames->retain();
    for(int i = 1 ;i < 9 ;i++)
    {
        CCSpriteFrame *frame = CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(CCString::createWithFormat("Blue_%d.png",i)->getCString());
        idleAnimFrames->addObject(frame);

    }
    CCAnimation *idleAnimation = CCAnimation ::createWithSpriteFrames(idleAnimFrames,float(1.0/60.0)) ;



    //ball collision and die
    CCArray* collidieAnimaFrames = CCArray::createWithCapacity(15);
    collidieAnimaFrames->retain();
    for (int i = 1;i < 15; i++)
    {
        CCSpriteFrame *frame = CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(CCString::createWithFormat("BlueColli_%d.png",i)->getCString());
        collidieAnimaFrames->addObject(frame);
    }
    CCAnimation* collidieAnimation = CCAnimation::createWithSpriteFrames(collidieAnimaFrames, float(1.0/5.0));


    this->m_actionIdle = CCRepeatForever::create(CCAnimate::create(idleAnimation));
    this->m_actionIdle->retain();


    this->m_actionColli = CCRepeat::create(CCAnimate::create(collidieAnimation), 1); //action for ball bigger and collision
    this->m_actionColli->retain();
  //  arrayAction->addObject(m_actionColli);


    m_pSprite1->runAction(m_actionIdle);


    Init();


}
void RootObject::Init()
{

    createBox2d();
}



void RootObject :: setBallBiger() //set ball bigger and collision
{
    if(m_actionState == kActionIdle) //when touch on ball, if ball idle, ball will bigger and collision with other ball
    {
        m_Bigger = true;
       m_pSprite1->stopAction(m_actionIdle);



         m_actionState = kActionBigger;
        m_pSprite1->runAction(m_actionColli);
    }
}


bool RootObject::getRect(CCPoint point) //use for touch on ball bigger
{
    m_Rect = CCRectMake(
    m_pSprite1->getPositionX() - (m_pSprite1->getTextureRect().size.width/2) * m_pSprite1->getScaleX(),
    m_pSprite1->getPositionY() - (m_pSprite1->getTextureRect().size.height/2) * m_pSprite1->getScaleY(),
m_pSprite1->getTextureRect().size.width * m_pSprite1->getScaleX(),
m_pSprite1->getTextureRect().size.height * m_pSprite1->getScaleY()
                        );

    if(m_Rect.containsPoint(point))
    {return true;}
    else return false ;
}

void RootObject ::createBox2d()
{

    m_ballBodyDef.type = b2_dynamicBody;
    m_ballBodyDef.position.Set(m_pSprite1->getPositionX()/PTM_RATIO,m_pSprite1->getPositionY()/PTM_RATIO);
    m_ballBodyDef.userData = m_pSprite1;

    m_ballBody = world->CreateBody(&m_ballBodyDef);


    //create ball definition
    b2CircleShape m_circle ;
    m_circle.m_radius = m_pSprite1->getContentSize().width/2/PTM_RATIO ;


    m_ballFixtureDef.filter.categoryBits = 0x0002; //this's not important 
    m_ballFixtureDef.filter.maskBits = 1 | 0x0008; 


    m_ballFixtureDef.shape = &m_circle;
    m_ballFixtureDef.density = 1.0f;
    m_ballFixtureDef.friction = 0.0f;

    m_ballFixtureDef.restitution = 1.0f;
    m_ballFixture = m_ballBody->CreateFixture(&m_ballFixtureDef);


    m_ballBody->ApplyLinearImpulse(m_force, m_ballBody->GetWorldCenter());


}
void RootObject::update(float dt)
{

}


void RootObject::collisionCallBack(RootObject* obj) //collision Call Back 
{
    if(m_Bigger ==  false) //first i use if(m_actionState == kActionIdle) but this condition can't not rune, cclog give garbage number., then i replace by bool m_bigger. check : if ball bigger = false will bigger after collsion 
    {
        m_Bigger = true;
        CCLog("%d",m_Bigger);
        m_pSprite1->stopAction(m_actionIdle);//error at here although in method setballbiger not error



        m_actionState = kActionBigger;

        m_pSprite1->runAction(m_actionColli);
    }

}


RootObject:: ~RootObject(void)
{
    this->m_ballBody->GetWorld()->DestroyBody(m_ballBody);

}

In tick method of helloworld scene:

    std::vector::iterator i = m_ListBall->begin();  //m_listball is vector object manage all ball
    std::vector::iterator end = m_ListBall->end();
// for (std::vector::iterator i = m_ListBall->begin();i!= m_ListBall->end(); i++) {
    for (; i!=end; ++i) {



        if((*i)->m_actionColli->isDone()==true) //when m_actionColli finish, it will remove sprite vs body .
        {

         this->removeChild((*i)->spritebatch);
         RootObject* ball = *i;
         delete  ball;

         if ( i != m_ListBall->end() )
         ManagerObject::Instance()->getListBall()->erase(i);  


         }


void HelloWorld ::ccTouchesEnded(CCSet* touches, CCEvent* event) //when touch on ball, ball will call function setBallBiger
{

    CCTouch* touch = (CCTouch*)( touches->anyObject() );
    CCPoint location = touch->getLocationInView();

    location = CCDirector::sharedDirector()->convertToGL(location);

    for (std::vector::iterator i = m_ListBall->begin();i!= m_ListBall->end(); i++) {
        if((*i)->getRect(location))
        {
            (*i)->m_ballBody->DestroyFixture((*i)->m_ballFixture);
            createBox2d((*i));
             (*i)->m_ballBody->SetLinearVelocity(b2Vec2(0,0));
            (*i)->setBallBiger();
        }
    }


    // Set up initial location of projectile
    CCSize winSize = CCDirector::sharedDirector()->getWinSize();

}

what is the size of the balls relative to PTM_RATIO? Make sure m_circle.m_radius at least 1. i.e.

in
m_circle.m_radius = m_pSprite1->getContentSize().width/2/PTM_RATIO

the value of m_circle.m_radius is >= 1;