Sprite Kit在移动父级SKNode后无法找到nodeAtPoint节点

4

嗨。

我在Sprite Kit中遇到了一个奇怪的问题。在调用跳跃方法时,我使用nodeAtPointcategoryBitMask来检测玩家是否触碰地面。

一切都按照预期运行。但是,为了在抽屉中显示一些可选按钮,当我使用SKAction moveTo:CGPoint移动父节点(我将地面和玩家都作为SKNode的子节点),玩家就不会跳跃。我NSLog pointBelowPlayer,它与之前相同,但是blockNode.physicsBody为空!这可能是Sprite Kit中的一个错误,还是我对继承和位置的基础知识缺失?

跳跃方法:

-(void)playerJump {

    // Player jump if on ground
    CGPoint pointBelowPlayer = CGPointMake(_player.position.x, _player.position.y-_player.size.height);
    SKNode *blockNode = [self nodeAtPoint:pointBelowPlayer];

    if (blockNode.physicsBody.categoryBitMask == groundCategory){
        [_player.physicsBody applyImpulse:CGVectorMake(0, 120.0f)];
    }
}
移动父节点的方法:
-(void)toggleDrawer {
    if (bDrawerVisible) {
        [_actionLayer runAction:[SKAction moveTo:CGPointMake(0, 0) duration:1]];
        bDrawerVisible = false;
    } else {
        [_actionLayer runAction:[SKAction moveTo:CGPointMake(0, 200) duration:1]];
        bDrawerVisible = true;
    }
}

创建SpriteNodes:

-(id)initWithSize:(CGSize)size {
    if (self = [super initWithSize:size]) {

        _actionLayer = [SKNode new];

        _player = [self createPlayer];
        [_actionLayer addChild:_player];

        _ground = [self createGround];
        [_actionLayer addChild:_ground];
}

-(SKSpriteNode *)createPlayer {

    SKSpriteNode *player = [SKSpriteNode spriteNodeWithImageNamed:@"redSquare.png"];
    player.name = @"player";
    player.scale = 0.5;
    player.position = CGPointMake(screenWidth/3, player.size.height*2);
    player.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:player.size];
    player.physicsBody.categoryBitMask = playerCategory;
    player.physicsBody.collisionBitMask = groundCategory;
    player.physicsBody.contactTestBitMask = noteCategory;

    return player;
}

-(SKSpriteNode *)createGround {

    SKSpriteNode *ground = [SKSpriteNode spriteNodeWithImageNamed:@"ground.png"];
    ground.name = @"ground";
    ground.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:ground.size];
    ground.physicsBody.dynamic = NO;
    ground.physicsBody.categoryBitMask = groundCategory;
    ground.physicsBody.collisionBitMask = playerCategory;
    ground.xScale = screenWidth/ground.size.width;;
    ground.position = CGPointMake(self.size.width/2, 0);

    return ground;
}
2个回答

5

好的,我解决了这个问题。 如果您有多个节点,在您点击的位置上,如果最深层的节点没有名称,则会返回null,或者返回最深层节点的名称。

因此,请使用以下代码遍历所有找到的节点:

UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInNode:self];
NSArray *buttonNodes = [self nodesAtPoint:location];
for (SKNode *node in buttonNodes)
{
    NSLog(@"%@", node.name);
}

另外,您可以使用NSLog(@"%f", node.zPosition);来获取zPosition,以查看哪一个在顶部。


只是为了澄清,nodeAtPoint返回该点最深的节点,而nodesAtPoint返回该点上所有节点的数组。 - Cooper Buckingham
这解决了我在将我的SK应用从iOS7迁移到iOS8时遇到的问题。谢谢! - DavidNorman

1

点上的节点可能是另一个节点(也许是您的背景?)。
使用node.name为节点命名,您可以通过将名称与equalToString:方法进行比较来检查节点是否相同。


感谢您的迅速回复!目前还处于开发初期,我还没有任何背景。在父级移动后(之前是“ground”),node.name返回(null),因此没有其他nodeAtPoint。 - Brean
@Brean它将返回null,因为名称未设置。为您的节点设置不同的名称,然后再次记录名称,看看会发生什么。 - Dvole
地面节点已经被命名,正如您可以从我的上面的代码中看到的那样。如果我在pointBelowPlayer处NSLog节点,则返回<SKScene> name:'(null)' frame:{{0, 0}, {1024, 768}},好像地面不存在。 - Brean

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接