2

I have an SKNode that has user interaction enabled and I am adding an SKEmitterNode to that and I want the user interaction to be disabled for just the child. This code does not work.

SKNode* parentNode = [[SKNode alloc] init];
parentNode.userInteractionEnabled = YES;
NSString* path = [[NSBundle mainBundle] pathForResource:@"ABCDEFG" ofType:@"xyz"];
SKEmitterNode* childNode = [NSKeyedUnarchiver unarchiveObjectWithFile:path];
childNode.userInteractionEnabled = NO;
[parentNode addChild:childNode];

I also tried setting user interaction to NO after adding to the parent. Is this possible or do I need to add the emitter to the parent's parent somehow?

san
  • 3,350
  • 1
  • 28
  • 40
miek
  • 743
  • 1
  • 8
  • 15
  • how are you checking for touches / user interaction. – DogCoffee Oct 08 '13 at 03:00
  • touchesBegan on the parent. If you tap the parent it animates like a button press and spawns a few particles. – miek Oct 10 '13 at 00:20
  • found this out today, Setting userInteractionEnabled on a node allows the node itself to receive events. That means you would implement touchesBegan:withEvent: on that actual object – DogCoffee Oct 10 '13 at 05:33
  • I am, but adding child nodes to the node with it enabled trickles down. So, if you tap the child, even if it doesn't have userInteractionEnabled = YES, the tap gets sent up the chain until something consumes it. That consumer being the parent in this case. – miek Oct 10 '13 at 16:33

2 Answers2

1

I'm sure there is a better way (and hope there is!!), but its a start.

Maybe this is how it should be done. Problem is if you have an emitter over a sprite, the touch doesn't pass through (well didn't in my testing).

  -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {

    for (UITouch *touch in touches) {

        UITouch *touch = [touches anyObject];
        CGPoint positionInScene = [touch locationInNode:self];
        SKSpriteNode *touchedNode = (SKSpriteNode *)[self nodeAtPoint:positionInScene];

        if (touchedNode.userInteractionEnabled) {
            NSLog(@"Name of node touched %@", touchedNode.name);
        }
        else {
            NSLog(@"Can't touch this! %@", touchedNode.name);
        }
    }
}
DogCoffee
  • 19,820
  • 10
  • 87
  • 120
  • That is causing some weirdness. It will randomly let me tap somewhere that isn't the parent (possibly because a previous emitter is still active). And sometimes it wont let me tap the parent, because of the particles being emitted. I want the emitted particles to be ethereal. – miek Oct 10 '13 at 00:17
  • @miek I agree, there has to be a better way. I haven't been able to make emitted particles to be ethereal – DogCoffee Oct 10 '13 at 00:23
0

I achieved this by sending a notification from the parent, to its parent with the location of the tap. The function in the parent-parent spawns the emitter with user interaction disabled and the target of the emissions set to the parent. Perhaps some code is in order.

In the parent:

UITouch *touch = [touches anyObject];
// to get the location in the scene
CGPoint location = [touch locationInNode:[self parent]];
NSDictionary* locationDic = [NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects: [NSNumber numberWithFloat:location.x],                                                                                          
                                                                                           [NSNumber numberWithFloat:location.y],
                                                                                           nil]
                                                        forKeys:[NSArray arrayWithObjects:@"loc_x", @"loc_y", nil]];
[[NSNotificationCenter defaultCenter] postNotificationName:@"Ntf_SpawnParticles"
                                                    object:nil
                                                  userInfo:locationDic];

In the parent's parent (the scene), register for the event:

[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(spawnParticles:)
                                             name:@"Ntf_SpawnParticles"
                                           object:nil];

Still in the parent's parent (the scene), implement "spawnParticles":

- (void)spawnRockDebris:(NSNotification *)ntf
{
    float x = [[[ntf userInfo] valueForKey:@"loc_x"] floatValue];
    float y = [[[ntf userInfo] valueForKey:@"loc_y"] floatValue];
    CGPoint location = CGPointMake(x, y);

    NSString* particlePath = [[NSBundle mainBundle] pathForResource:@"CoolParticles" ofType:@"sks"];
    SKEmitterNode* particleEmitterNode = [NSKeyedUnarchiver unarchiveObjectWithFile:particlePath];
    // set up other particle properties here
    particleEmitterNode.position = location;
    particleEmitterNode.userInteractionEnabled = NO;
    particleEmitterNode.targetNode = [self childNodeWithName:@"particleTargetNode"];
    [self addChild:particleEmitterNode];
}
miek
  • 743
  • 1
  • 8
  • 15