发射器不随父节点旋转



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

我正在修改SpriteKit,我似乎无法让发射器节点以我想要的方式与我的宇宙飞船一起旋转。

我观看了苹果科技对话会,他们描述了制造宇宙飞船并使用发射器进行推力排气,但他们将飞船锁定为只面向一个方向。

在我的实验中,我试图让玩家精灵(宇宙飞船)向任何方向移动,我为玩家提供了旋转和滚动功能,但粒子发射器似乎不会随玩家旋转。

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

场景

-->世界节点

-->播放器节点

---->玩家精灵

---->发射器节点

我的理论是,如果我旋转(玩家节点),它应该旋转它的两个子节点,并且它确实旋转了它们,但发射器继续以相同的方向发射。

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

这是我用来旋转的

-(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

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

使用其他节点类型

您真正想要的是粒子被繁殖,但之后独立于发射极节点。当发射器节点旋转后,新粒子获得新的方向,而旧粒子粒子保持其原来的方向。

然后给出了一个使用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;
}

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

我知道这是一个老问题,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帧进行这种检查。

我希望这能帮助到别人!

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

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

如果你正在寻找一个"中间地带",角度随着玩家一起旋转,而已经渲染的粒子没有"粘"在发射器上,试试这个:

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

    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;
}];

最新更新