0

我正在为 iOS 7 开发游戏,它使用 Spritekit。

主要的 skspritenode 是一架直升机,当这架直升机接触到收缩奖励皮卡时,直升机会收缩以使用户更容易导航。以下是按预期工作的缩小直升机的代码(self 指的是直升机 skspritenode):

SKAction *scaleHeli = [SKAction scaleBy:.70 duration:1];
SKAction *setPhysicsBody = [SKAction runBlock:^{
self.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:CGSizeMake(self.size.width, self.size.height)];
self.physicsBody.mass = 0.080944441;
self.physicsBody.restitution = 1.0f;
self.physicsBody.allowsRotation = FALSE;
self.physicsBody.categoryBitMask = APAColliderTypeShip;
self.physicsBody.collisionBitMask = APAColliderTypeCavePiece;
self.physicsBody.contactTestBitMask = APAColliderTypeCavePiece | APAColliderTypeBonusPickup;
}];

SKAction *seq = [SKAction sequence:@[scaleHeli, setPhysicsBody]];

[self runAction:seq];
_shrinkEnabled = true;

我有一个持续预定时间的收缩奖金的计时器设置:

-(void)startShrinkTimer
{
    //Creating the timer for the shield
    _timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self    selector:@selector(countDownShrinkDuration) userInfo:Nil repeats:true];
    _timerSeconds = 15;
}

-(void)countDownShrinkDuration
{
    if(_timerSeconds > 0)
    {
        --_timerSeconds;
    }
    else if(_timerSeconds == 0)
    {
        [_sceneRef disableShrinkBonus];
        [_timer invalidate];
    }

    if(_timerSeconds < 5)
    {
        [_sceneRef shrinkWearingOut];
    }
}

如果计时器小于 5 秒,则调用 shrinkWearingOut 函数,该函数将标签添加到淡入淡出的节点(self 指的是直升机 skspritenode):

SKLabelNode *downLbl = [[SKLabelNode alloc] init];
downLbl.text = @"↓";
downLbl.fontColor = [UIColor whiteColor];
downLbl.fontSize = 9.0f;
downLbl.horizontalAlignmentMode = SKLabelHorizontalAlignmentModeLeft;
downLbl.position = CGPointMake(0,-30);
downLbl.zPosition = 5;

SKAction *fadeOut = [SKAction fadeOutWithDuration: .2];
SKAction *fadeIn = [SKAction fadeInWithDuration: .2];
SKAction *pulse = [SKAction sequence:@[fadeOut,fadeIn]];

SKAction *pulseForever = [SKAction repeatActionForever:pulse];

SKSpriteNode *wearingOut = [[SKSpriteNode alloc] init];
wearingOut.name = @"wearingOut";

[wearingOut addChild:downLbl];

[wearingOut runAction:pulseForever];

[self addChild:wearingOut];

一旦计时器达到零,就会调用 disableShrink 函数,它会尝试移除脉动节点并将直升机缩放到其原始大小(self 指的是直升机 skspritenode):

[[self childNodeWithName:@"wearingOut"] removeFromParent];

SKAction *scaleHeli = [SKAction scaleBy:1.3 duration:1];
SKAction *setPhysicsBody = [SKAction runBlock:^{
    self.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:CGSizeMake(self.size.width, self.size.height)];
    self.physicsBody.mass = 0.080944441;
    self.physicsBody.restitution = 0.0f;
    self.physicsBody.allowsRotation = FALSE;
    self.physicsBody.categoryBitMask = APAColliderTypeShip;
    self.physicsBody.collisionBitMask = APAColliderTypeCavePiece;
    self.physicsBody.contactTestBitMask = APAColliderTypeCavePiece | APAColliderTypeBonusPickup;

    _shrinkEnabled = false;
}];

SKAction *seq = [SKAction sequence:@[scaleHeli, setPhysicsBody]];

[self runAction:seq];

问题#1:这行代码:[[self childNodeWithName:@"wearingOut"] removeFromParent]; 实际上并没有从直升机节点中删除脉动节点,我在这里设置了一个断点并验证该节点不为零,但它似乎仍然没有删除该节点。非常令人沮丧,因为我使用了完全相同的代码行和不同名称的不同奖励拾取,它工作得很好。唯一的区别是另一个奖励拾取是使用 skshapenode,无论哪种方式它们都从 sknode 继承,所以它们的功能应该相同。

问题#2:脉冲节点已成功添加,但仅脉冲几次,我觉得这很奇怪,因为我在不同的奖励上使用了确切的一组 skaction,并且该奖励脉冲直到它从直升机节点中删除。

4

1 回答 1

0

观察:

你不应该使用 NSTimer。而是使用update:SKScene 的方法来执行定时操作,并在需要时将其转发给需要它的子节点。或者使用 SKActionrunBlockwaitForDuration. NSTimer 可能不会与 Sprite Kit 更新/渲染循环同步运行,如果节点或场景暂停,它们也不会停止触发。

检查您是否没有多个名为“wearingOut”的子节点。听起来你可能添加了不止一个。使用 NSTimer 实际上可能会导致奇怪的行为,因为 Sprite Kit 可能会延迟从场景中添加/删除节点,因此添加/删除节点的时间可能是一个问题。这是一个疯狂的猜测。

脉动问题也可能表明多个精灵,也许它们是异步脉动的,因此它们看起来没有脉动。或者尝试fadeAlphaTo:操作。

一般来说,尝试使用记录在案的初始化程序。如果你只是这样做可能会有问题[[SKLabelNode alloc] init]。我遇到了一些问题[SKSpriteNode node],例如即使在设置纹理之后也无法绘制。而是做[SKLabelNode labelNodeWithFontNamed:@"Arial"]或任何其他指定的初始化程序。请参阅Sprite Kit 框架参考

于 2014-03-20T19:47:19.313 回答