【问题标题】:Custom SKSpriteNode not detected during touch触摸期间未检测到自定义 SKSpriteNode
【发布时间】:2013-10-21 00:09:52
【问题描述】:

在学习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 时,这段代码工作得很好,而不是我自己的子类。有什么建议吗?

【问题讨论】:

    标签: ios sprite-kit


    【解决方案1】:

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

    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。这将基本上和你习惯的一样工作(在你想继承你的英雄之前)。因此,您在问题中设置的 touchesBegan 将起作用。

    @implementation HeroSprite
    
    - (id) init {
        if (self = [super init]) {
            self = [HeroSprite spriteNodeWithImageNamed:@"Spaceship"];
            [self setUpHeroDetails];
    
        }
        return self;
    }
    
    -(void) setUpHeroDetails {
        self.name = @"heroNode";
    }
    
    @end
    

    【讨论】:

    • 虽然我是 SpriteKit 和 Objective-C 的新手,但我不明白我们如何创建这些类的实例?
    • 我没有把那个代码放进去,就像你创建一个普通的 SKSprite 一样创建,但是使用 HeroSprite。
    • 很棒的方法!太棒了
    【解决方案2】:

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

    self.userInteractionEnabled = YES;
    

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

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

      • 在我的容器内触摸 SKLabelNode 时遇到问题,但是使用此行“touchedNode = (SKSpriteNode*)self.touchBeganNode.parent;”拯救我的一天。
      • self.touchBeganNode 是自定义变量吗?
      • 是的,它在我的代码中,但我想我的意思是touchedNode,我刚刚更新了答案。
      【解决方案4】:

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

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

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

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

      【讨论】:

      • 尽管 OP 从未要求过这个,但我很想看到您正在谈论的委托解决方案的代码。我在我的 SKSpriteNode 子类中成功处理了 touchEnded,但还想在 SKView 中触发 touchesEnded 方法,如果您在子类上启用 userInteractionEnabled,则情况并非如此。
      【解决方案5】:

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多