StackBuddy
StackBuddy

Reputation: 577

Trouble detecting a touch on a nested custom sprite layer

I have a layer, HelloWorldLayer below, where touch works anywhere, but I'd like it to work only when touching a sprite in the layer -- turtle below.

If I try to add self.isTouchEnabled = YES; onto the CCTurtle layer it says

property isTouchEnabled not found on object type CCTurtle

my output reads as follows

2013-01-08 20:30:14.767 FlashToCocosARC[6746:d503] cocos2d: deallocing

2013-01-08 20:30:15.245 FlashToCocosARC[6746:d503] playing walk animation2

Here's my HelloWorldLayer code:

#import "HelloWorldLayer.h"
#import "CCTurtle.h"

@implementation HelloWorldLayer

+(CCScene *) scene
{
    CCScene *scene = [CCScene node];
    HelloWorldLayer *layer = [HelloWorldLayer node];
    [scene addChild: layer];
    return scene;
}

-(id) init
{
    if( (self=[super init])) {
        turtle= [[CCTurtle alloc] init];
        [turtle setPosition:ccp(300, 100)];
        [self addChild:turtle];
        ///addChild:child z:z tag:aTag;
        self.isTouchEnabled = YES;
        turtle. tag=4;
    //

    }
return self;
}



//- (void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
//{
//    // Processing all touches for multi-touch support
//    UITouch *touch = [touches anyObject];
//    if ([[touch view] isKindOfClass:[turtle class]]) {
//        NSLog(@"[touch view].tag = %d", [touch view].tag);
//        [self toggleTurtle];
//    }
//}
-(BOOL)containsTouch:(UITouch *)touch {
    CGRect r=[turtle textureRect];
    CGPoint p=[turtle convertTouchToNodeSpace:touch];
    return CGRectContainsPoint(r, p );
}
- (void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    //////GENERAL TOUCH SCREEN
    for (UITouch *touch in touches) {
        CGPoint touchLocation = [touch locationInView:[touch view]];
        touchLocation = [[CCDirector sharedDirector] convertToGL:touchLocation];
        [self toggleTurtle];
        /////
    }

}
-(void) toggleTurtle
{
    NSLog(@"playing walk animation2");
   [turtle playAnimation:@"walk_in" loop:NO wait:YES];
}



@end

//hello world.h

    #import "cocos2d.h"
    #import "CCTurtle.h"

    @interface HelloWorldLayer : CCLayer 
    {
    CCTurtle                *turtle;
    }

    +(CCScene *) scene;

    @end

//CCturtle

    #import <Foundation/Foundation.h>
    #import "FTCCharacter.h"

    @interface CCTurtle : FTCCharacter <FTCCharacterDelegate, CCTargetedTouchDelegate>
    {

    }
    @end

I'm using Cocos2D cocos2d v1.0.1 (arch enabled), and am testing on ipad 4.3 simulator. with thanks Natalie

ive tried to put the touches directly into ccturtle.m so it can handle its own touches using CCTargetedTouchDelegate as above but using

CCturtle/// I changed files to this trying a different way to find the touched area...

    - (CGRect)rect
   {
   CGSize s = [self.texture contentSize];
   return CGRectMake(-s.width / 2, -s.height / 2, s.width, s.height);
   }

   -(BOOL) didTouch: (UITouch*)touch {
   return CGRectContainsPoint(self.rect, [self convertTouchToNodeSpaceAR:touch]);
   //return CGRectContainsPoint( [self rect], [self convertTouchToNodeSpaceAR: touch] );
   }

   -(BOOL) ccTouchBegan:(UITouch*)touch withEvent: (UIEvent*)event {
   NSLog(@"attempting touch.");
   if([self didTouch: touch]) {
   return [self tsTouchBegan:touch withEvent: event];
   }
   return NO;
   }

but still wont compile as still returns the error "Property 'is TouchEnabled' not found on object type 'CCTurtle*'

am really not sure what i can do to get it to run now... and really need to get this working (i suppose i could make invisible buttons, but it would be nicer to be able to find the ccturtle properly and to understand what im doing wrong... hope someone can help

Upvotes: 1

Views: 576

Answers (3)

StackBuddy
StackBuddy

Reputation: 577

Thanks to Prototypical the issue was solved, Although the CCTurtle was a layer with a type of sprite on it was nested sprites which meant that cocos2d had problems creating the correct bounding box for my "contains touch method"

so with a bit of magic he combined his "get full bounding box" method to the contains touch method to account for the children of the sprite, and the code now relies on collision detection to process the touch. currently im happily working away on some nice icons for him in return

but wanted to say thank-you to all that helped, and hope that this method comes in handy for anyone with the same problem!

Upvotes: 0

Sylvan
Sylvan

Reputation: 536

If you want your CCTurtle object to accept targeted touches, you can do it by specifying that it conforms to the CCTargetedTouchDelegate protocol. In your CCTurtle @interface, you declare it like so:

@interface CCTurtle : CCNode <CCTargetedTouchDelegate>

Then in the implementation, you tell it to accept touches and implement the ccTouch methods:

@implementation CCTurtle

-(id) init {
.
.
    [[CCDirector sharedDirector].touchDispatcher addTargetedDelegate:self priority:1 swallowsTouches:YES];
    return self;
}

-(void) onExit {
    [[CCDirector sharedDirector].touchDispatcher removeDelegate:self];
}

-(BOOL) ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event { 
    CGPoint location = [[CCDirector sharedDirector] convertToGL:[touch locationInView:[touch view]]];
    if (CGRectContainsPoint([self boundingBox], location] {
        // some code here
    }
}


-(void)ccTouchMoved:(UITouch *)touch withEvent:(UIEvent *)event { // code here }
-(void)ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event { // code here}
-(void)ccTouchCancelled:(UITouch *)touch withEvent:(UIEvent *)event { // code here}

Upvotes: 0

Morion
Morion

Reputation: 10860

First of all, I cannot see anywhere calling of containsTouch: method. And here are several advices:

Use boundingBox instead of textureRect to get local rect of your node (your turtle, in this case). Or just replace containsTouch: method to your turtle class to incapsulate this. It can be helpful, for example, if you want to make touch area of your turtle bigger/smaller. You will just need to change one little method in your turtle class.

In your ccTouchesBegan:withEvent: method just check for every turtle if it is hit by this touch. Then, for example, you can create dictionary, with touch as the key and array of corresponding turtles as the value. Then you just need to update all turtles positions for moved touch in your ccTouchesMoved:withEvent: method and remove this array of turtles from the dictionary in ccTouchesEnded:withEvent: and ccTouchCancelled:withEvent: method.

Upvotes: 1

Related Questions