Custom SKSpriteNode not detected during touch

纵然是瞬间 提交于 2019-12-18 02:41:38

问题


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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!