I have a class “Hero”, subclassed from CCSpriteBatchNode (cocos2d):
@interface Hero : CCSpriteBatchNode {...}
I’m initing it like this:
Hero *hero;
...
hero = [[Hero alloc] initWithWorld:world];
Here is init method of Hero:
-(id) initWithWorld:(b2World*)world
{
if (self = [super init])
{
...
}
return self;
}
Till this moment all works fine: I can add hero as a child to my layer, and it will be displayed correctly. But then, I’m trying to get some data from hero. I have this method in Hero class:
-(b2Body*) getBody; //in Hero.h
-(b2Body*) getBody //in Hero.mm
{
return selfBody;
}
and my application crashes just after calling [hero getBody]; with error:
* Terminating app due to uncaught exception ‘NSInvalidArgumentException’, reason: ‘-[CCSpriteBatchNode getBody]:
unrecognized selector sent to instance 0x42bde0’
so, he tries to find method getBody in CCSpriteBatchNode class. offcorse, he cant find it there. But WHY he tries to find it there? Why not in Hero class?
P.S. all my classes are *.mm. I need it to support box2d.
EDIT
The ony time I use hero between initing and calling getBody is adding it to CCLayer:
[self addChild:hero z:0 tag:kTagParentNode]; //self - CCLayer subclass
getBody is called from tick method:
[self schedule:@selector(tick:)];
...
-(void)tick:(float)dt
{
CGPoint scaledVelocity = ccpMult(leftJoystick.velocity, 480.0f);
if (scaledVelocity.y > CGPointZero.y)
{
[objectControls jump:[hero getBody]];
}
if (scaledVelocity.x > CGPointZero.x)
{
}
}
While it’s hard to tell what’s causing the issue without seeing much code, I advise you to rethink your architecture.
A
CCSpriteBatchNodeis an object that’s used by the cocos2d engine to render batched sprites. Is yourHeroreally such an object? I don’t think so. The Hero should be a class on it’s own and have ahas onerelation to aCCSpriteBatchNodeand ab2Body.Why? There are several reasons for this. First and foremost it’s going to decouple your
Heroimplementation from the interface imposed by cocos2d. If the creators of cocos2d decide to change some implementation details, your class might no longer work if it inherits from aCCNode. Also think about encapsulation: Does a visual component really have to know about player logic?If you split up your architecture you’re going to make your code better readable, easier to maintain and also easier to port to another platform if that’s ever going to happen. For a similar post, see this question on gamedev.SE.