Kay Lucas
Kay Lucas

Reputation: 589

Cocos2d execute a CCLayer function in one of it's children

I'm building an iPad game for a study project and I'm stuck trying to have one of my objects (which inherits from CCSprite) to call a function on the CCLayer.

The situation: I have an instance of wordObject (inherits from CCSprite) on my CCLayer. When the object gets touched it logs something and should execute a function on it's parent, the CCLayer, to create a new object.

What I have so far detects the touch and logs a message, but I can't find a way to execute the function on the CCLayer, hence my question.

When programming in another language I would just pass the CCLayer pointer as a parameter to the init function of my object. I tried doing that by extending the initWithSprite function this way:

//touch function
- (BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event {
        CGPoint location = [touch locationInView: [touch view]];
        if (CGRectContainsPoint([self boundingBox], location)) {
            CCLOG(@"Woah");
            [parentLayer foundWord:@"test" atLocation:ccp(100.0f, 100.0f) withZValue:(int)1000 andPoints:100];
            CCLOG(@"Delegate should have executed");

            return YES;
        }
        CCLOG(@"Touch detected, I'm located at %@ and the touch position is %@.", NSStringFromCGRect([self boundingBox]), NSStringFromCGPoint(location));
        return NO;
    }

// Extended init function, I have no normal init function anymore (but I don't think I need that, tried it and it gave crashes
-(id)initWithSpriteFrame:(CCSpriteFrame*)spriteFrame andParent:(CCLayer *)layer{
        [super initWithSpriteFrame:spriteFrame];
        self = [super init];
        if(self != nil){
            parentLayer = layer;
        }
        return self;
    }

The problem is after using this the object no longer responds to touch input (this is probably caused by me doing something wrong with the initialization of the object).

However, there is another way to do this and from what I understand this way is better in Objective C. I should be able to create a protocol for the function I need and then call that function in my object using delegation. The code I've written for this:

//CommonProtocols.h the file with the protocols. It is included in the CCLayer and in the object
@protocol GameplayScrollingLayerDelegate
-(void)foundWord:(NSString *)word atLocation:(CGPoint)location withZValue:(int)ZValue andPoints:(int)points;
@end

//Layer.h, subscribing the class to the protocol so it knows where it should delegate to
@interface Layer : CCLayer <GameplayScrollingLayerDelegate>  {
    //some stuff omitted due to not being relevant.
}

//Layer.m, nothing done here, I've just added the function which I described in the protocol file
-(void)foundWord:(NSString *)word atLocation:(CGPoint)location withZValue:(int)ZValue andPoints:(int)points{
    // Function gibberish doing what I want it to do
}

//Object.h create the delegate
@interface Object : GameObject <CCTargetedTouchDelegate> {
    id <GameplayScrollingLayerDelegate> delegate;
}

@property (nonatomic,assign) id <GameplayScrollingLayerDelegate> delegate;


//Object.m synthesize the delegate and try to execute the function
@synthesize delegate
//... code omitted ...
-(id)init{
    //default init stuff
    [delegate foundWord:@"test" atLocation:ccp(100.0f, 100.0f) withZValue:(int)1000 andPoints:100];
}

My lack of knowledge of working with protocols or interfaces probably caused me to omit something in the process. Although it doesn't give me any errors or warnings, it doesn't execute the function like I want it too. (I've got demo app that's using it and there it works perfectly but I just can't find the piece of code I'm missing).

Any suggestions on how I can fix this? Thanks for reading and hopefully answering my problem!

Upvotes: 0

Views: 1532

Answers (1)

Andrew
Andrew

Reputation: 24846

It is totally ok to have a CCSprite subclass what you've done. It should not be a problem (only if you were not using the existing field name). But if your sprite has a CCLayer as a parent the you can simple access it from sprite (or even CCNode)

CCLayer *layer = (CCLayer*) self.parent;

PS: You can't change the state of an object just passing pointer to it somewhere until you call some methods through this pointer.

Upvotes: 1

Related Questions