objective-ccocos2d-iphonebox2dbox2d-iphone

Check the class of an object from Box2d's user data


I am trying to determine the type of object when detecting collision with Box2d. I want to be able to assign the user data to an object and check to see if its of the correct class type

id object = b->GerUserData():

Then

if([object isKindOfClass:[MyClassObject class]])

However i just get the error "Cannot initialize a variable of type'id' with an rvalue of type 'void*'

Can anyone help me out.

Thanks


Solution

  • Your problem is you are trying to assign an object of type 'id' to a void * type

    The method call body->GetUserData(); returns a void pointer. Here it is as defined in the header file of b2Body.h

    /// Get the user data pointer that was provided in the body definition.
    void* GetUserData() const;
    

    Now, if you are using ARC (Automatic Reference Counting), you need to perform an additional step to cast it back.

     id object = (__bridge id) b->GetUserData();
    

    If you are not using ARC, then...

     id object = (id) b->GetUserData();
    

    As for checking the type, there are many ways to do this. I personally prefer having an enum called GameObjectType. I can then assign the type in the appropriate constructor of the object. Here is an example of how I do it in my games

     for (b2Body * b = world->GetBodyList(); b != NULL; b = b->GetNext()) {
    
        Box2DSprite * sprite = (__bridge Box2DSprite*) b->GetUserData();
        id obj = (__bridge id) b->GetUserData();
    
    
        if (sprite.gameObjectType == kGroundTypeStatic
            || sprite.gameObjectType == kWallType
            || sprite.gameObjectType == kGroundTypeDynamic) {
    
            // Insert Logic here
        } // end if
    
        sprite.position = ccp(b->GetPosition().x * PTM_RATIO, b->GetPosition().y * PTM_RATIO);
        sprite.rotation = CC_RADIANS_TO_DEGREES(b->GetAngle() * -1);
    
    } // end for
    

    Here is how I would go about creating the sprite (Using ARC)

    b2BodyDef bodyDef;
    bodyDef.type = b2_dynamicBody;
    bodyDef.position = b2Vec2(location.x/PTM_RATIO,
                          location.y/PTM_RATIO);
    
    // Setting the enum value
    self.gameObjectType = kTankType;
    self->body = self->world->CreateBody(&bodyDef);
    self->body->SetUserData((__bridge void*) self); // Obtain sprite object later
    
    GB2ShapeCache * shapeCache = [GB2ShapeCache sharedShapeCache];
    
    [shapeCache addFixturesToBody:self->body forShapeName:@"Earth_Tank"];
    
    self.anchorPoint = [shapeCache anchorPointForShape:@"Earth_Tank"];
    

    Hope this helps