触摸期间未检测到自定义SKSpriteNode

时间:2013-10-21 00:09:52

标签: ios sprite-kit

在学习SpriteKit时,我正在尝试制作一款小型冒险游戏。我正在创建一个英雄,并将其添加到场景中,然后在touchesBegan:期间,我检测到触摸是否源自英雄,并相应地采取行动。

如果我将英雄添加为SKSpriteNode,则触摸会检测到他。如果我将他添加为SKSpriteNode的子类,则触摸不会!添加的区别:

_heroNode = [SKSpriteNode spriteNodeWithImageNamed:@"hero.png"];

VS

_heroNode = [[ADVHeroNode alloc] init];

init看起来像这样:

- (id) init {
    if (self = [super init]) {

        self.name = @"heroNode";
        SKSpriteNode *image = [SKSpriteNode spriteNodeWithImageNamed:@"hero.png"];
        [self addChild:image];
    }
    return self;
}

将英雄作为SKSpriteNode的子类添加工作的意义在于它被添加到场景中,但触摸不会检测到他。我的touchesBegan:看起来像这样:

-(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;
    }
}

令人沮丧的是,这个代码在添加直接SKSpriteNode时工作得很好,而不是我自己的子类。有什么建议吗?

5 个答案:

答案 0 :(得分:23)

以下是一些子类化Hero

的示例方法

<强> SKNode

子类SKNode此方法需要您的节点监视触摸,因此需要监视self.userInteractionEnabled属性。

@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

另一种“更简单”的方式,如果您只想将SKSpriteNode子类化。这将基本上与您使用的相同(在您想要继承您的Hero之前)。所以你的touchesBegan,在你的问题中设置将起作用。

@implementation HeroSprite

- (id) init {
    if (self = [super init]) {
        self = [HeroSprite spriteNodeWithImageNamed:@"Spaceship"];
        [self setUpHeroDetails];

    }
    return self;
}

-(void) setUpHeroDetails {
    self.name = @"heroNode";
}

@end

答案 1 :(得分:10)

请务必在init方法中添加此内容。

self.userInteractionEnabled = YES;

由于某些原因,在子类化时默认情况下不启用此选项。至少对我来说,它只在手动启用时才有效。

答案 2 :(得分:3)

我经常检查被触摸的节点的父节点,直到找到我要控制的类。 这是一个代码段。

while (touchedNode.parent)
    {
        if ([touchedNode isKindOfClass:[GameObject class]])
            break;
        else
            touchedNode = (SKSpriteNode*)self.touchedNode.parent;
    }

答案 3 :(得分:1)

它只是检测到了这个精灵的触摸。

创建对象SKSpriteNode时,它将自行控制。这意味着,当触摸开始时,它意味着此对象接收此触摸而不是SKView。

因此,如果要检测此触摸,则必须在此对象上编写此代码,而不是在SKView上。如果您想在SKSpriteNode上触摸时在SKView上执行任何操作,则可以使用委托执行此操作。

如果你无法理解我的答案,请随时提出更多问题。

答案 4 :(得分:0)

您的ADVHeroNode是SkNode或没有图像的SkSpriteNode。它们都没有任何范围,它们可以说是重点。 nodeAtPoint将找不到它们:但是图像子SKSpriteNode将会找到它们。由于您明确检查节点的名称,因此检查失败。

您可以为图像指定一个名称,然后检查它,然后引用它的父项来获取ADVHeronode实例。或者直接检查node.parent的名称。