0

I use the following code block and when I debug I see that SKShapeNode's accumulated frame is now {{-160.03586, -42.431793}, {470.03586, 519.50903}}instead of something like {{0,0}, {100,300}}.

If I comment out this whole particle code, accumulatedFrame is meaningful again.

I need it to be meaningful as I use nodesAtPoint in touchesBegan. Any nonsense value causes nodesAtPoint to find irrelevant nodes too as accumulatedFrame is now weird for all and they all intersect...

I use the following code block and I couldn't find out the problem. What do I miss here?

NSString *path = [[NSBundle mainBundle] pathForResource:@"MyParticle" ofType:@"sks"];
SKEmitterNode *particles = [NSKeyedUnarchiver unarchiveObjectWithFile:path];

particles.position = CGPointMake(_selectedNode.frame.size.width/2, _selectedNode.frame.size.height/2);

[particles runAction:[SKAction sequence:@[[SKAction waitForDuration:.2],
                                        [SKAction fadeAlphaTo:0 duration:0.2],
                                        [SKAction removeFromParent]]] completion:^{
                                [particles removeFromParent];
}];
[_selectedNode addChild:particles];
frankish
  • 6,738
  • 9
  • 49
  • 100

1 Answers1

3

accumulatedFrame is what it sounds like, it is the minimum rectangle that contains all the graphical objects of your node. An emitternode will actually add nodes to the object it is added to. It works exactly as intended when calculating the accumulated frame.

The way to get around this is to have the emitter node have a "target node". SKEmitterNode has a property called .targetNode. It basically means that it will drop its sprites into that node.

I've found it a good method to have a single SKNode which contains all of my emitted nodes. This is then separate from the layers I click.

Check the SKEmitterNode class reference for more information on the targetNode.

SKEmitter Node class reference

Theis Egeberg
  • 2,556
  • 21
  • 30
  • I added `particles.targetNode=_selectedNode;` before `[_selectedNode addChild:particles];`and now it doesn't break `accumulatedFrame` calculation and my `touchesBegan` works correctly. But I am still curious about the reason of why targetNode=nil causes incorrect calculations.. I debugged it and there are no `children` left in the parent node, so It should already calculate it correctly.. Do you have any idea on how `targetNode=nil` breaks it's parent node's accumulatedFrame calculation? – frankish Jul 11 '14 at 18:16
  • I found out that, this time it breaks some other node and touchesBegan can't work correctly to identify touched object while Emitter is still alive.. – frankish Jul 11 '14 at 18:25
  • The target node is where the emitter will drop its particles. You should add them to a different layer all together. I layer completely away from your nodes. The SKEmitterNode is placed in a node, which is where its position is. But where it drops its particles is set by the targetNode. – Theis Egeberg Jul 12 '14 at 11:11
  • `_selectedNode` is where I want it to linked to and I want it to continue emitting particles with the same location of `_selectedNode` dynamically. `self` is the main Scene. Here is the code. This doesn't feel right: `SKNode *tNode=[[SKNode alloc]init]; particles.targetNode=tNode; [_selectedNode addChild:particles]; [self addChild:tNode];` – frankish Jul 12 '14 at 11:55
  • 1
    Add the particles to the selected node. Set the targetNode of the particles to the parent node of the selectedNode. It's absolutely right what you're doing. Where the particles is added is where they get their starting position from. The targetnode is where the particles are actually spawned. – Theis Egeberg Jul 12 '14 at 20:40