从父级(Sprite Kit)目标 C 中移除节点

Posted

技术标签:

【中文标题】从父级(Sprite Kit)目标 C 中移除节点【英文标题】:Removing Node From Parent (Sprite Kit) Objective C 【发布时间】:2016-04-07 21:45:00 【问题描述】:

我正在创建一个节点从右向左移动的横向滚动游戏。问题是当它离开屏幕时它不会自行移除。我可以让它工作的唯一方法是不多次调用我的 bat 节点方法。但我需要多个蝙蝠出现在屏幕上。问题似乎是当我使用 SKAction waitforDuration 或 performSelector afterDelay 多次调用我的 bat 方法时。

蝙蝠法

-(void) addBats

int random = arc4random_uniform(self.size.height/2);

bats = [SKSpriteNode spriteNodeWithImageNamed:@"Bat1.png"];
bats.physicsBody = [SKPhysicsBody bodyWithTexture:bats.texture size:bats.frame.size];
bats.position = CGPointMake(self.size.width * 9, random);
bats.zPosition = 4;
[bats setScale:0.3];
bats.physicsBody.categoryBitMask = enemyCategoryL4;
bats.physicsBody.dynamic = NO;
bats.physicsBody.contactTestBitMask = playerCategoryLevel4;
bats.physicsBody.usesPreciseCollisionDetection = YES;

[L4foregroundNode addChild:bats];

SKAction *up = [SKAction moveByX:-1 y: -40 duration:1];
SKAction *down = [SKAction moveByX:-1 y:40 duration:1];
SKAction *action1 = [SKAction repeatActionForever:[SKAction sequence:@[up, down]]];

SKAction *action2 = [SKAction moveByX:-self.size.width * 10  y:0 duration:40.0];
SKAction *group = [SKAction group:@[action1, action2]];

[bats runAction:group];

-(void) update:(NSTimeInterval) currentTime

if(bats.position.x < -50)

    [bats removeFromParent]; 
    [self addBats];

上述方法仅在我每次调用蝙蝠一次时才有效。有没有一种方法可以让我多次调用并在每次离开屏幕时移除球棒?

【问题讨论】:

bats 是否定义为场景的 iVar(SKSpriteNode 类型)(只是检查以获得完整图片)? 是的,它是 SKSpriteNode 的 iVar。你认为这可能是问题吗? 好的,所以你这里的代码很乱:) 你想要的是创建动作序列,或者按照建议使用完成处理程序。当动作完成时,也就是蝙蝠离开屏幕时,您将它们从其父级中移除...... 另外,如果老节点不在屏幕上(你看不到它),你怎么知道它实际上没有从场景中移除? 哦,我明白了...如果您使用[SKAction waitForDuration]; 在一定延迟后调用addBats,那么您将失去用户5556671 指出的引用。 (这仍然意味着节点实际上并没有像你说的那样离开屏幕;)因为你可以看到它们)。 【参考方案1】:

这是一个关于如何创建精灵的示例,将其移动直到最终离开屏幕,然后立即将其移除:

#import "GameScene.h"


@interface GameScene()

@property (nonatomic, strong)SKSpriteNode *sprite;

@end

@implementation GameScene

-(void)didMoveToView:(SKView *)view

    self.sprite = [SKSpriteNode spriteNodeWithColor:[SKColor purpleColor] size:CGSizeMake(50.0f,50.0f)];

    //Place a sprite on right edge of the screen (I assume that your view and a scene have same size)
    self.sprite.position = CGPointMake(self.frame.size.width, self.frame.size.height / 2.0f);

    SKAction *moveSprite = [SKAction moveTo:CGPointMake(-self.sprite.size.width, self.frame.size.height / 2.0f) duration:5.0f];

    SKAction *removeSprite = [SKAction removeFromParent];

    SKAction *sequence = [SKAction sequence:@[moveSprite, removeSprite]];

    [self addChild:self.sprite];

    [self.sprite runAction:sequence withKey:@"moving"];



-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event

    if (self.sprite.parent) 
        NSLog(@"Sprite has a parent");
    else
        NSLog(@"Sprite doesn't have a parent");
    


@end

尝试使用或不使用[SKAction removeFromParent] 的这段代码(查看两​​种情况下精灵离开屏幕后打印的内容)。

【讨论】:

【参考方案2】:

对于您在 addBats 中创建的每个 bat,您可以使用 runAction:completion: 来运行滚动操作,然后在完成块中从父节点中删除节点。问题可能是当您添加多个节点时,您会丢失对要删除的节点的引用。

这段代码应该做你想做的事(未经测试):

SKAction *up = [SKAction moveByX:-1 y:-40 duration:1]; 
SKAction *down = [SKAction moveByX:-1 y:40 duration:1];
SKAction *action1 = [SKAction repeatActionForever:[SKAction sequence:@[up, down]]];
[bats runAction:action1];

SKAction *scroll = [SKAction moveByX:-self.size.width * 10 y:0 duration:40.0];
[bats runAction:scroll completion:^
   [bats removeFromParent];
];

【讨论】:

以上是关于从父级(Sprite Kit)目标 C 中移除节点的主要内容,如果未能解决你的问题,请参考以下文章

如何在Swift中正确地从父节点中删除SKSpriteNode的子类(要从数组中移除,屏幕上的空格......)?

Xcode 如何自动从其父节点中删除 skspritenode

Swift 中 Sprite Kit SKAction 的问题

Sprite Kit中的碰撞检测未检测到碰撞

Sprite-Kit:节点不会向左移动

使用 Swift 在 sprite kit 中的多个场景中重用相同的 sprite 节点