Okay, I finally got my targeting system to work. I did as Vramin suggested and instead of iterating through the enemy array to check for touches I made my CCSprite subclass confrom to the <CCTargetedTouchDelegate> protocol and also set up an instance variable of type BOOL called isTargeted. Like so:
@interface Enemy : CCSprite <CCTargetedTouchDelegate> {...
BOOL isTargeted_;...
I then added a property:
@property (nonatomic,assign)BOOL isTargeted;
And then in my interface section of Enemy.m I synthesized the property and explicitly assigned isTargeted_ to it like so:
@implementation Enemy
...
@synthesize isTargeted = isTargeted_;
I also go on to implement the appropriate methods for handling touches later in the Enemy.m interface section. Please Note: This code is almost exactly what appears in the TouchesTest demo that is included in the tests folder of the cocos2d-iphone XCode Project I just left out the state enum stuff for sake of simplicity. These test projects are invaluable, and I would be missing patches of hair if it wasn't for good examples like these.
- (void)onEnter
{
[[CCTouchDispatcher sharedDispatcher] addTargetedDelegate:self priority:0 swallowsTouches:YES];
[super onEnter];
}
- (void)onExit
{
[[CCTouchDispatcher sharedDispatcher] removeDelegate:self];
[super onExit];
}
- (BOOL)containsTouchLocation:(UITouch *)touch
{
return CGRectContainsPoint(self.rect, [self convertTouchToNodeSpaceAR:touch]);
}
- (BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event
{
if ( ![self containsTouchLocation:touch] ){
self.isTargeted = NO;
return NO;
} else {
self.isTargeted = YES;
return YES;
}
}
Let me know if any of this is unnecessary or may lead to bugs. I am not quite sure if it was necessary to declare the instance variable "BOOL isTargeted_"; I might have been able to just declare and synthesize the property, let me know if that's so.
Then in my Player.h I declared:
-(void)getTargetInArray:(NSMutableArray*)enemyArray;
And defined it in Player.m:
-(void)getTargetInArray:(NSMutableArray*)enemyArray {
for(Enemy *enemy in enemyArray){
if(enemy.isTargeted)
self.target = enemy;
}
}
The rest of the code is in my game scene where I declare the following instance vars
@interface Layer : CCLayer {
...
Player *player_;
NSMutableArray *enemies_;
}
I then alloc and init the array and set up a scheduled selector "update:" in my layer's init method and fill it with my enemies. And finally in my scheduled update method I call that instance method from the Player class:
-(void)update:(ccTime)dt
{
...
[player_ getTargetInArray:enemies_];
...
}
So I'm sure there's some inefficiencies in this code, as I said before I'm relatively new to all of this. I'll leave the performance tweaks till I get everything else working. But please tell me if there's any unnecessary or buggy code so I can fix it. I hope this HUGE post can help someone who wants to add basic tap-and-target functionality to an RPG style game.