0

I made a game with SpriteKit. I structured my game by coding a GameScene (SKScene) and a separate enemy class. I want the spawning enemies to shoot a particle e.g. every 2 seconds (just moving an SKEmitterNode by the y axis) I tried to do it with a timer, but it doesn't really work.

I call my Enemy class from the gaming Scene with this code:

GameScene.m

 -(void)enemiesLevel1{
    EnemyClass* wave1 = [[EnemyClass alloc] init];
    [wave1 enemiesLevel1:self];
 }

And I am basically calling this method from EnemyClass.m

-(void)enemiesLevel1:(SKScene *)scene
{
    enemy = [SKSpriteNode spriteNodeWithImageNamed:Enemy];
    //Enemy Path
    (...)

    SKAction *followPath2 = [SKAction followPath:pathRef2
                                        asOffset:NO
                                    orientToPath:YES
                                        duration: pathSpeed];




    SKAction *forever = [SKAction repeatActionForever:followPath2];



    //PhysicsBody Eigenshaften
    enemy.physicsBody =[SKPhysicsBody bodyWithCircleOfRadius:enemy.size.width];
    enemy.physicsBody.dynamic = YES;
    enemy.physicsBody.categoryBitMask = enemyCategory;

    [enemy runAction:forever];
    [scene addChild:enemy];

    NSTimer *timer;
    timer = [NSTimer scheduledTimerWithTimeInterval:0.5
                                         target:self
                                       selector:@selector(weaponParticle)
                                       userInfo:nil
                                        repeats:YES];
    }




-(void)weaponParticle{


    screenHeight = self.frame.size.height;
    screenWidth = self.frame.size.width;

    //Schuss-Particles

    enemyParticlePath = [[NSBundle mainBundle] pathForResource:@"ShootFire" ofType:@"sks"];
    enemyParticle = [NSKeyedUnarchiver unarchiveObjectWithFile:enemyParticlePath];

    enemyParticle.physicsBody =[SKPhysicsBody bodyWithCircleOfRadius:0.2];
    enemyParticle.physicsBody.categoryBitMask = shootCategory;
    enemyParticle.physicsBody.contactTestBitMask = playerCategory;

    //Schuss-Action
    moveDown = [SKAction moveByX:0.0 y:-screenHeight duration:1.0];
    remove = [SKAction removeFromParent];
    weaponShot = [SKAction sequence:@[moveDown, remove]];

    enemyParticle.position = CGPointMake(enemy.position.x, enemy.position.y+10);



    [self addChild:enemyParticle];
    [enemyParticle runAction: weaponShot];

}

The enemies are spawning 1 by 1 just how I wanted, but they can't shoot. Can anyone help me out?

user3545063
  • 681
  • 8
  • 17

1 Answers1

2

Instead of scheduling NSTimer try something like this:

SKAction *shoot = [SKAction runBlock:^{
      // add code that shoots here
}];

SKAction *wait = [SKAction waitForDuration:0.5];
[enemy runAction:[SKAction repeatActionForever:[SKAction sequence:@[shoot, wait]]]];
almas
  • 7,090
  • 7
  • 33
  • 49
  • great idea! still doesn't work for some reason? I checked if the code will actually run by putting an NSLog under this action and the console displays the nslog but the enemies still don't shoot. Any ideas? – user3545063 Oct 20 '14 at 21:23
  • I tried it again and now I'm getting this game breaking error: `2014-10-20 23:32:49.659 Pixel Plane[1791:352128] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Attemped to add a SKNode which already has a parent: name:'(null)' particleTexture: 'spark.png' (20 x 16) position:{0, 0} accumulatedFrame:{{inf, inf}, {inf, inf}}'` I am guessing it's because I already have the same particle used by the player node in the game scene? how can i prevent this? – user3545063 Oct 20 '14 at 21:34
  • 1
    You must create a new node/particle every single time. You cannot reuse them. The error message clearly states that. Basically, you cannot call 'addChild' method to the same node twice. Post your 'weaponParticle' code if you need more help. – almas Oct 20 '14 at 21:38
  • i posted it already under the EnemyClass.m file. What code do I have to use if I'd like to "reuse" a node, instead of addChild? – user3545063 Oct 21 '14 at 04:53
  • I thought that can you have to remove a node from his parent before adding a new one. I also implemented this in my code. But why isn't it working? – user3545063 Oct 21 '14 at 13:51
  • I don't really see problems with your code. The only thing is that I don't see where you declare 'enemyParticle' variable (it is not declared in 'weaponParticle' method). Do you use it somewhere else outside of 'weaponParticle'? – almas Oct 21 '14 at 15:24
  • 1
    I discovered my bug, there were actually two addChild methods on the particle node. If anyone runs into the same problem: [I set up an exception breakpoint to discover the added nil node](https://developer.apple.com/library/ios/recipes/xcode_help-breakpoint_navigator/articles/adding_an_exception_breakpoint.html) – user3545063 Oct 21 '14 at 19:02