Search code examples
iosobjective-csprite-kitskemitternode

Emitter not rotating with parent node


Code --> http://pastebin.com/W3DMYjXa

I am tinkering with SpriteKit and I cannot seem to get an emitter node to rotate with my spaceship the way I would like.

I watched the Apple Tech Talks Session where they described making a spaceship and using an emitter for the thrust exhaust, but they lock the ship to only face one direction.

In my experiment I am trying to allow the player sprite (spaceship) to travel in any direction, I have rotation and scrolling working for the player, but the particle emitter doesn't seem to rotate with the player.

my hierarchy looks something like this

Scene

-->World Node

-->Player Node

---->Player Sprite

---->Emitter Node

My theory is that If I rotate (Player Node) it should rotate both of its children, and it does rotate them, but the emitter continues to emit in the same direction.

I can change the emission angle manually, but it seems needlessly complicated.

here is what I am using to rotate

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

}

Am I missing something here?

Here is a video of this in action

http://youtu.be/NGZdlB9-X_o


Solution

  • I'm fairly certain there is a bug in spritekit to do with the targetNode and rotation. The other answer seems to suggest this is expected behavior, but that ignores that the docs explicitly give this situation as a motivation for the existence of targetNode.

    Working with Other Node Types

    What you really want is for the particles to be spawned, but thereafter be independent of the emitter node. When the emitter node is rotated, new particles get the new orientation, and old particles maintain their old orientation.

    It then gives an example using targetEmitter on how to achieve this. However, the example code does not work.

    It seems that setting targetNode breaks particle rotation.

    UPDATE: I found a workaround.

    Spritekit is failing to adjust the SKEmitterNode.emissionAngle property when SKEmitterNode.targetNode is set. You can work around this by setting it manually after actions have been processed.

    Assuming that your SKEmitterNode has only one parent, you can do something like this in your scene.

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

    Note that if there are multiple ancestor nodes which may be rotated, you will need to loop through them and add all of their zRotations together.