¿Cómo hacer que los objects reaccionen a toques en Cocos2D?

Bien, entonces estoy comenzando a aprender más sobre Coco2D, pero estoy un poco frustrado. Muchos de los tutoriales que he encontrado son para versiones obsoletas del código, así que cuando miro y veo cómo hacen ciertas cosas, no puedo traducirlo a mi propio progtwig, porque muchas cosas han cambiado. Dicho eso, estoy trabajando en la última versión de Coco2d, versión 0.99.

Lo que quiero hacer es crear un sprite en la pantalla (Listo) y luego, cuando toco ese sprite, puedo hacer que "algo" suceda. Por ahora, hagamos una alerta. Ahora, tengo este código trabajando con la ayuda de un amigo. Aquí está el file de encabezado:

// When you import this file, you import all the cocos2d classes #import "cocos2d.h" // HelloWorld Layer @interface HelloWorld : CCLayer { CGRect spRect; } // returns a Scene that contains the HelloWorld as the only child +(id) scene; @end 

Y aquí está el file de implementación:

 // // cocos2d Hello World example // http://www.cocos2d-iphone.org // // Import the interfaces #import "HelloWorldScene.h" #import "CustomCCNode.h" // HelloWorld implementation @implementation HelloWorld +(id) scene { // 'scene' is an autorelease object. CCScene *scene = [CCScene node]; // 'layer' is an autorelease object. HelloWorld *layer = [HelloWorld node]; // add layer as a child to scene [scene addChild: layer]; // return the scene return scene; } // on "init" you need to initialize your instance -(id) init { // always call "super" init // Apple recommends to re-assign "self" with the "super" return value if( (self=[super init] )) { // create and initialize a Label CCLabel* label = [CCLabel labelWithString:@"Hello World" fontName:@"Times New Roman" fontSize:64]; // ask director the the window size CGSize size = [[CCDirector shanetworkingDirector] winSize]; // position the label on the center of the screen label.position = ccp( size.width /2 , size.height/2 ); // add the label as a child to this Layer [self addChild: label]; CCSprite *sp = [CCSprite spriteWithFile:@"test2.png"]; sp.position = ccp(300,200); [self addChild:sp]; float w = [sp contentSize].width; float h = [sp contentSize].height; CGPoint aPoint = CGPointMake([sp position].x - (w/2), [sp position].y - (h/2)); spRect = CGRectMake(aPoint.x, aPoint.y, w, h); CCSprite *sprite2 = [CCSprite spriteWithFile:@"test3.png"]; sprite2.position = ccp(100,100); [self addChild:sprite2]; //[self registerWithTouchDispatcher]; self.isTouchEnabled = YES; } return self; } // on "dealloc" you need to release all your retained objects - (void) dealloc { // in case you have something to dealloc, do it in this method // in this particular example nothing needs to be released. // cocos2d will automatically release all the children (Label) // don't forget to call "super dealloc" [super dealloc]; } - (void)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { UITouch *touch = [touches anyObject]; //CGPoint location = [[CCDirector shanetworkingDirector] convertCoordinate:[touch locationInView:touch.view]]; CGPoint location = [touch locationInView:[touch view]]; location = [[CCDirector shanetworkingDirector] convertToGL:location]; if (CGRectContainsPoint(spRect, location)) { UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Win" message:@"testing" delegate:nil cancelButtonTitle:@"okay" otherButtonTitles:nil]; [alert show]; [alert release]; NSLog(@"TOUCHES"); } NSLog(@"Touch got"); } 

Sin embargo, esto solo funciona para 1 object, el sprite para el que creo el CGRect. No puedo hacerlo por 2 sprites, que estaba probando. Entonces, mi pregunta es esta: ¿Cómo puedo hacer que todos los sprites en la pantalla reaccionen al mismo evento cuando se tocan?

Para mi progtwig, el mismo evento debe ejecutarse para todos los objects del mismo tipo, por lo que debería ser un poco más fácil. Intenté hacer una subclass de CCNode y sobre escribir el método, pero eso simplemente no funcionó en absoluto … así que estoy haciendo algo mal. ¡La ayuda sería apreciada!

Pasando por el proyecto "Touches" en cocos2D y viendo si veo cómo lo hicieron. Parece que hicieron una subclass y sobrescribieron los methods:

 - (BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event - (void)ccTouchMoved:(UITouch *)touch withEvent:(UIEvent *)event - (void)ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event 

Entonces ahora entiendo por qué el mío no funciona … mmm …

Entiendo. Tuve que agregar un poco más de código a la class personalizada:

Archivo de cabecera:

 // // CustomCCNode.h // Coco2dTest2 // // Created by Ethan Mick on 3/11/10. // Copyright 2010 Wayfarer. All rights reserved. // #import "cocos2d.h" @interface CustomCCNode : CCSprite <CCTargetedTouchDelegate> { } @property (nonatomic, readonly) CGRect rect; @end 

Implementación:

 // // CustomCCNode.m // Coco2dTest2 // // Created by Ethan Mick on 3/11/10. // Copyright 2010 Wayfarer. All rights reserved. // #import "CustomCCNode.h" #import "cocos2d.h" @implementation CustomCCNode - (CGRect)rect { CGSize s = [self.texture contentSize]; return CGRectMake(-s.width / 2, -s.height / 2, s.width, s.height); } - (BOOL)containsTouchLocation:(UITouch *)touch { return CGRectContainsPoint(self.rect, [self convertTouchToNodeSpaceAR:touch]); } - (void)onEnter { [[CCTouchDispatcher shanetworkingDispatcher] addTargetedDelegate:self priority:0 swallowsTouches:YES]; [super onEnter]; } - (void)onExit { [[CCTouchDispatcher shanetworkingDispatcher] removeDelegate:self]; [super onExit]; } - (BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event { NSLog(@"ccTouchBegan Called"); if ( ![self containsTouchLocation:touch] ) return NO; NSLog(@"ccTouchBegan returns YES"); return YES; } - (void)ccTouchMoved:(UITouch *)touch withEvent:(UIEvent *)event { CGPoint touchPoint = [touch locationInView:[touch view]]; touchPoint = [[CCDirector shanetworkingDirector] convertToGL:touchPoint]; NSLog(@"ccTouch Moved is called"); } - (void)ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event { NSLog(@"ccTouchEnded is called"); } @end 

Soy un principiante en esto, pero este file me salvó muchos problemas, ahora entiendo mucho más cosas, y la forma de instanciar correctamente esto es: (al less, cómo lo hice)

 +(id)scene{ CustomCCNode *myNode = [CustomCCNode spriteWithFile:@"myPng.png"]; myNode.position = ccp(150,150); [scene addChild:myNode]; return scene; } 

Abra la console y observe los posts que se envían cuando se activan los events táctiles.