发射器不与父节点一起旋转

时间:2014-02-26 13:29:14

标签: ios objective-c sprite-kit skemitternode

代码 - > http://pastebin.com/W3DMYjXa

我正在修补SpriteKit,我似乎无法按照我想要的方式让我的太空船旋转发射器节点。

我观看了Apple Tech Talks Session,他们描述了制造宇宙飞船并使用发射器进行推力排气,但他们将船只锁定在一个方向。

在我的实验中,我试图允许玩家精灵(宇宙飞船)向任何方向行进,我有旋转和滚动为玩家工作,但粒子发射器似乎不随玩家旋转。

我的层次结构看起来像这样

场景

- >世界节点

- >播放器节点

---->玩家精灵

---->发射器节点

我的理论是,如果我旋转(播放器节点),它应该旋转它的两个子节点,它会旋转它们,但发射器继续以相同的方向发射。

我可以手动改变发射角度,但似乎不必要地复杂化。

这是我用来旋转的东西

-(void)rotatePlayerToDirection:(TTDirection)direction {

    CGFloat radDir;
    CGFloat emiDir;
    scrollDirection = direction;

    switch (direction) {
        case TTUp:
            radDir = 0;
            emiDir = 3.142;
            break;
        case TTRight:
            radDir = 4.712;
            emiDir = 1.571;
            break;
        case TTDown:
            radDir = 3.142;
            emiDir = 0;
            break;
        case TTLeft:
            radDir = 1.571;
            emiDir = 4.712;
            break;

        default:
            break;
    }



    SKAction *rotatePlayer = [SKAction rotateToAngle:radDir duration:0.1 shortestUnitArc:YES];

    [playerNode runAction:rotatePlayer];

}

我在这里错过了什么吗?

以下是此操作的视频

http://youtu.be/NGZdlB9-X_o

3 个答案:

答案 0 :(得分:3)

我相当确定spritekit中有一个与targetNode和rotation相关的错误。另一个答案似乎表明这是预期的行为,但忽略了文档明确地将这种情况作为targetNode存在的动机。

Working with Other Node Types

  

你真正想要的是产生粒子,但之后是   独立于发射器节点。当发射器节点是   旋转,新粒子获得新的方向,旧的   粒子保持旧的方向。

然后给出了一个使用targetEmitter的例子来说明如何实现这一点。但是,示例代码不起作用。

似乎设置targetNode会打破粒子旋转。

更新:我找到了解决方法。

当设置了SKEmitterNode.targetNode时,Spritekit无法调整SKEmitterNode.emissionAngle属性。您可以通过在处理操作后手动设置它来解决此问题。

假设您的SKEmitterNode只有一个父级,您可以在场景中执行类似的操作。

- (void)didEvaluateActions
{
    // A spaceship with a thrust emitter as child node.
    SKEmitterNode *thrust = (SKEmitterNode *)[self.spaceship childNodeWithName:@"thrust"];
    thrust.emissionAngle = self.spaceship.zRotation + STARTING_ANGLE;
}

请注意,如果有多个可以旋转的祖先节点,则需要循环遍历它们并将所有zRotations一起添加。

答案 1 :(得分:1)

我知道这是一个老问题,OP可能已经找到了一个解决方案或解决方法,但我认为我会增加两便士值,以防它帮助其他人。

我刚刚开始使用SpriteKit和Swift,我正在开发一种游戏,其中节点飞来飞去并相互碰撞,经常改变旅行方向。

我向每个节点添加一个发射器,并且最初发现当节点旋转并改变方向时,发射“轨迹”保持固定。然后我读到发射器应该将其目标节点设置为不是它的子节点,而是它们都存在的场景。

这至少使粒子轨迹变得扭曲并且变得逼真而不是仅向一个方向喷射。

但节点可以旋转并改变方向,我希望粒子在与其行进方向相反的方向上远离节点 - 就像从飞机或火箭的烟雾轨迹一样。

由于节点可能会旋转,因此将发射器的发射角设置为节点的z旋转不起作用。所以......

我跟踪字典中的所有屏幕节点,当它们离开屏幕时将它们从场景中移除。

所以在didSimulatePhysics中,我使用相同的字典来获取节点并根据速度矢量计算行进角度,然后相应地设置发射器的发射角度:

import Darwin

// in your scene class...

override func didSimulatePhysics() {
    removeOffScreenParticles()
    for (key,particle) in particles {
        let v = particle.physicsBody!.velocity
        particle.trail!.emissionAngle = atan2(v.dy, v.dx) - CGFloat(M_PI)
    }
}

我知道这个计算和调整是针对每个屏幕节点在每个帧中执行的,因此如果性能成为一个问题,可能会使用我的帧计数器仅对每第n帧执行此检查。

我希望这有助于某人!

答案 2 :(得分:0)

您正在将发射器的targetNode属性设置为背景。请注意,这会强制发射器的粒子由背景节点渲染,并且它们将被视为背景是其父级。因此,粒子不会改变角度,因为背景的旋转不会改变。

移除[emitter setTargetNode:backgroundNode],发射器的发射角度应与播放器一起正确旋转。

如果你正在寻找一个“中间地带”,角度与玩家一起旋转,而已经渲染的粒子没有“卡住”发射器,请尝试:

  • 首先,不要在发射器上设置targetNode(默认为nil)。
  • 其次,正如您要运行旋转操作一样,暂时将targetNode设置为另一个节点,并在完成时将其重置为nil(以便粒子可以旋转):

    emitter.targetNode = backgroundNode;
    [playerNode runAction:rotatePlayer completion:^{
       emitter.targetNode = nil;
    }];
    

请注意,结果也是“中间地面” - 当目标节点发生变化时,发射器'抽吸'(先前的粒子被移除,新的粒子被新的目标节点渲染)。希望有所帮助。

除此之外,没有真正直接的方法来实现这一点 - 手动设置发射角度可能是最简单的方法。这是一种方法,在运行旋转之前(发射器目标节点仍为零,也就是说,不需要硬编码发射角度):

    float originalAngle = emitter.emissionAngle;
    emitter.emissionAngle = emitter.emissionAngle - radDir;
    [playerNode runAction:rotatePlayer completion:^{
        emitter.emissionAngle = originalAngle;
   }];