12

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

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

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

对比

_heroNode = [[ADVHeroNode alloc] 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,而不是我自己的子类。有什么建议么?

4

5 回答 5

24

以下是一些将您的英雄子类化的示例方法

SK节点

此方法的子类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

另一种“更简单”的方式,如果你只想继承 a SKSpriteNode. 这将基本上和你习惯的一样工作(在你想继承你的英雄之前)。因此,您在问题中设置的 touchesBegan 将起作用。

@implementation HeroSprite

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

    }
    return self;
}

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

@end
于 2013-10-21T07:58:26.460 回答
12

请务必将其添加到您的 init 方法中。

self.userInteractionEnabled = YES;

由于某些原因,当您进行子类化时,默认情况下不会启用此功能。至少对我来说,它仅在手动启用时才有效。

于 2014-12-07T18:37:19.240 回答
3

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

while (touchedNode.parent)
    {
        if ([touchedNode isKindOfClass:[GameObject class]])
            break;
        else
            touchedNode = (SKSpriteNode*)self.touchedNode.parent;
    }
于 2013-10-21T14:37:03.887 回答
1

它仅检测到对此精灵的触摸。

当您创建一个对象 SKSpriteNode 时,它​​将控制自己。这意味着,当触摸开始时,这意味着这个对象接收到这个触摸而不是 SKView。

所以如果你想检测这个触摸,你必须把这段代码写在这个对象上而不是SKView上。如果您想在 SKSpriteNode 上发生触摸时在 SKView 上执行任何操作,您可以使用委托来执行此操作。

如果您无法理解我的回答,请随时询问。

于 2013-10-21T06:41:21.467 回答
0

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

您可以为图像命名,并检查该名称,然后参考其父级以获取 ADVHeronode 实例。或者直接检查 node.parent 的名称。

于 2013-10-21T00:50:20.530 回答