0

I have an SKEmitterNode centered on my player to leave a trail of particles. My player has a physics body and it's moved by physics, not by manually updating it's position.

The issue I'm having is that when the speed of my player increases the particles are emitted from a point behind the player. I discovered that this is happening because the particles are emitted in the "evaluate actions" part of the frame cycle. My player is afterwards moved by the "simulate physics" part.

The solution I found as a workaround is to move the SKEmitterNode (in the update callback) to the point where my player will be after the physics calculations. This is the code I used:

particleEmitter.position = CGPointMake(
    player.position.x + player.physicsBody!.velocity.dx * dt,
    player.position.y + player.physicsBody!.velocity.dy * dt
)

UPDATE
At first I had my emitter as a child node of the player, then is when I observed the problem.
I also tried to sync the emitter position exactly to the player position, without accounting for distance moved since the last update (velocity * dt), same problem.

My question is, what would be the correct way of solving this?

UPDATE 2
I've created a playground demonstrating the issue. Here I have the emitter as a child of the player. The more you increase the player's velocity the bigger the gap between the player and the emitted particles.
https://github.com/ovidiupruteanu/SKEmitterNodeTest-Playground


Here is the frame cycle from the apple docs enter image description here

Ovidiu
  • 851
  • 5
  • 9
  • What's your question? Are you looking for alternatives to your implementation? – rickster Nov 05 '14 at 21:26
  • After some more tests and seeing @0x141E's answer I did find some issues with my workaround. For example, when the player comes to a complete stop (after traveling at high velocity) by colliding with another object some particles are generated beyond the point where my player stopped. – Ovidiu Nov 06 '14 at 04:34

2 Answers2

0

Your code only estimates the next position of the player. It doesn't consider other factors that may affect the player's position, such as collisions, force fields, linear damping, etc. I suggest you set the emitter's position to the player's position in the didSimulatePhysics callback or add the emitter as a child of player.

0x141E
  • 12,613
  • 2
  • 41
  • 54
  • I did try both your suggestions. The problem is that the particles are already generated when it reaches the didSimulatePhysics callback, so just setting the position to the player position at that point doesn't help. I know what I did is an estimate of the player's next position, it is however a good estimate from what I have seen. – Ovidiu Nov 05 '14 at 23:28
  • If the player is moving so fast that it outruns its children, you are probably exceeding the limits of what sprite kit can handle. – 0x141E Nov 06 '14 at 08:13
0

Rather than manually repositioning the emitter on every frame, let SpriteKit do that work for you: make the emitter a child node of the player sprite, and the emitter point will stay at the same location relative to the player whenever the player moves.

If you go this route, you might have a problem with the emitted particles also following the player in ways you don't want. You can resolve this by setting the emitter's targetNode to the node containing the player.

rickster
  • 124,678
  • 26
  • 272
  • 326