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