4

コード --> http://pastebin.com/W3DMYjXa

私は SpriteKit をいじっていますが、エミッター ノードを宇宙船で思い通りに回転させることができないようです。

私は Apple Tech Talks Session を見ました。彼らは宇宙船を作り、推力排気にエミッターを使用することを説明していましたが、彼らは船を一方向にしか向かないようにロックしていました。

私の実験では、プレーヤー スプライト (宇宙船) が任意の方向に移動できるようにしようとしています。プレーヤーの回転とスクロールが機能していますが、パーティクル エミッターはプレーヤーと一緒に回転していないようです。

私の階層は次のようになります

シーン

-->ワールドノード

-->プレイヤーノード

---->プレイヤースプライト

---->エミッタノード

私の理論では、(Player Node) を回転させると、その両方の子が回転するはずであり、それらは回転しますが、エミッターは同じ方向に放出し続けます。

放射角度を手動で変更できますが、必要以上に複雑に思えます。

これが私が回転するために使用しているものです

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

4

3 に答える 3

3

targetNode と回転に関係する spritekit にバグがあることは確かです。他の答えは、これが予想される動作であることを示唆しているように見えますが、ドキュメントがこの状況を targetNode の存在の動機として明示的に示していることを無視しています。

他のノード タイプの操作

本当に必要なのは、パーティクルがスポーンされ、その後はエミッタ ノードから独立していることです。エミッタ ノードが回転すると、新しいパーティクルは新しい向きになり、古いパーティクルは古い向きを維持します。

次に、これを達成する方法について targetEmitter を使用した例を示します。ただし、サンプル コードは機能しません。

targetNode を設定すると、パーティクルの回転が壊れているようです。

更新: 回避策を見つけました。

SKEmitterNode.targetNode が設定されている場合、Spritekit は SKEmitterNode.emissionAngle プロパティの調整に失敗します。アクションが処理された後に手動で設定することで、これを回避できます。

SKEmitterNode の親が 1 つだけであると仮定すると、シーンで次のようなことができます。

- (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 を一緒に追加する必要があることに注意してください。

于 2014-04-22T06:52:34.627 に答える
1

これは古い質問であることは知っています.OPはおそらく解決策または回避策を見つけましたが、他の人の助けになる場合に備えて、2ペンスの価値があると思いました.

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 フレームごとにのみこのチェックを行うことになるでしょう。

これが誰かに役立つことを願っています!

于 2015-02-04T15:08:50.640 に答える
0

エミッタのtargetNodeプロパティを背景に設定しています。これにより、エミッタのパーティクルがバックグラウンド ノードによって強制的にレンダリングされ、バックグラウンドが親であるかのように扱われることに注意してください。背景の回転は変わらないので、パーティクルは角度を変えません。

削除する[emitter setTargetNode:backgroundNode]と、エミッターの放射角度がプレーヤーに合わせて正しく回転するはずです。

既にレンダリングされたパーティクルがエミッタに「くっつかない」一方で、角度がプレーヤーとともに回転する「中間」を探している場合は、次のことを試してください。

  • まず、エミッターに targetNode を設定しないでください (デフォルトは nil です)。
  • 次に、回転アクションを実行しようとしているときに、targetNode を一時的に別のノードに設定し、完了したら nil にリセットします (パーティクルが回転できるようにするため)。

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

結果も「中間」であることに注意してください。ターゲット ノードが変更されると、エミッタが「パフ」します (以前のパーティクルは削除され、新しいターゲット ノードによって新しいパーティクルがレンダリングされます)。それが役立つことを願っています。

それ以外に、これを達成するための本当に簡単な方法はありません。結局のところ、放出角度を手動で設定するのが最も簡単な方法かもしれません。回転を実行する直前に、これを行う 1 つの方法を次に示します (エミッタ ターゲット ノードはまだ nil です。また、放出角度をハードコードする必要はありません)。

    float originalAngle = emitter.emissionAngle;
    emitter.emissionAngle = emitter.emissionAngle - radDir;
    [playerNode runAction:rotatePlayer completion:^{
        emitter.emissionAngle = originalAngle;
   }];
于 2014-02-26T14:46:26.137 に答える