问题
In learning SpriteKit, I am trying to make a small adventure game. I am creating a hero, and adding it to the scene, and then later, during touchesBegan:
, I detect if the touch originated on the hero, and take actions accordingly.
If I add the hero as a SKSpriteNode
the touch detects him. If I add him as a subclass of SKSpriteNode
the touch does not! The difference in adding:
_heroNode = [SKSpriteNode spriteNodeWithImageNamed:@"hero.png"];
vs
_heroNode = [[ADVHeroNode alloc] init];
The init looks like this:
- (id) init {
if (self = [super init]) {
self.name = @"heroNode";
SKSpriteNode *image = [SKSpriteNode spriteNodeWithImageNamed:@"hero.png"];
[self addChild:image];
}
return self;
}
Adding the hero as a subclass of SKSpriteNode works in the sense that it is added to the scene, but the touch doesn't detect him. My touchesBegan:
looks like this:
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
/* Called when a touch begins */
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInNode:self];
SKNode *node = [self nodeAtPoint:location];
if (YES) NSLog(@"Node name where touch began: %@", node.name);
//if hero touched set BOOL
if ([node.name isEqualToString:@"heroNode"]) {
if (YES) NSLog(@"touch in hero");
touchedHero = YES;
}
}
Frustratingly, this code works just fine when adding a straight up SKSpriteNode
, and not my own subclass of it. Any suggestions?
回答1:
Here are some example ways to subclass your Hero
SKNode
Subclass an SKNode
this method requires your node to monitor for touches, hence the self.userInteractionEnabled property.
@implementation HeroSprite
- (id) init {
if (self = [super init]) {
[self setUpHeroDetails];
self.userInteractionEnabled = YES;
}
return self;
}
-(void) setUpHeroDetails
{
self.name = @"heroNode";
SKSpriteNode *heroImage = [SKSpriteNode spriteNodeWithImageNamed:@"Spaceship"];
[self addChild:heroImage];
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint locationA = [touch locationInNode:self];
CGPoint locationB = [touch locationInNode:self.parent];
NSLog(@"Hit at, %@ %@", NSStringFromCGPoint(locationA), NSStringFromCGPoint(locationB));
}
@end
SKSpriteNode
The other "easier" way, if you just want to subclass a SKSpriteNode
. This will work essentially the same as you are use to (before you wanted to subclass your Hero). So your touchesBegan, as set up in your question will work.
@implementation HeroSprite
- (id) init {
if (self = [super init]) {
self = [HeroSprite spriteNodeWithImageNamed:@"Spaceship"];
[self setUpHeroDetails];
}
return self;
}
-(void) setUpHeroDetails {
self.name = @"heroNode";
}
@end
回答2:
Just be sure to add this in your init method.
self.userInteractionEnabled = YES;
For some reasons this is not enabled by default when you subclass. At least for me it worked only when manually enabled.
回答3:
I usually check the touched node's parent until i find the class i want to control. Here's a code snippet.
while (touchedNode.parent)
{
if ([touchedNode isKindOfClass:[GameObject class]])
break;
else
touchedNode = (SKSpriteNode*)self.touchedNode.parent;
}
回答4:
It just detected touch on this sprite only.
When you create an Object SKSpriteNode, it will control itself. It mean, when a touch begin on it, it mean this object receive this touch not the SKView.
So if you want to detect this touch, you must write this code on this object not on the SKView. If you want to do anything on SKView when a touch happen on SKSpriteNode, you can use delegate to do this.
Feel free to ask more if you cannot understand what I answer.
回答5:
Your ADVHeroNode is either a SkNode or SkSpriteNode with no image. Neither will have any extents, they're points so to speak. They will not be found by nodeAtPoint: but the image child SKSpriteNode will. Since you're explicitly checking for the node's name, the check fails.
You could give the image a name, and check for that and then refer to its parent to gethe ADVHeronode instance. Or just check node.parent's name directly.
来源:https://stackoverflow.com/questions/19484396/custom-skspritenode-not-detected-during-touch