0

I am making a game in which there is a player and multiple enemies (at least, that's important for now). I have and NSTimer that calls a method that calles the Enemy class that spawns an enemy every x amount of time. The method calls the spawn method in side the Enemy class which returns a SKSpriteNode that gets spawned in the GameScene.

Now, whenever the Enemy is falling from the sky (which is what it does: it spawns on top and then falls down), Its name is @"fallingEnemy" and whenever it hits the ground this name gets updated to @"staticEnemy" (I do this using contact bit masks) What I want to happen is the following: Whenever the enemy hasn't hit the ground yet and hits the player before it hits the ground, I want it to kill the player and when the enemy has already hit the ground and the player touches it, I want the player to die.

I do this by checking (with an If statement) if the name of the enemy is @"fallingEnemy" whenever the player contacts the enemy. The problem lies here: In my GameScene I have a property call aNewEnemy (SKSpriteNode) and it gets set equal to the SKSpriteNode that the Enemy class returns every time it is called by the NSTimer. Then when the enemy hits the ground the name changes to @"staticEnemy" for a while until a new enemy spawns, because then the name gets set back to @"fallingEnemy". I completely understand why this is happening, because it is very obvious, but I just don't no another way to do it. Anyone got any suggestions? There probably is a much easier way to do this that I'm not familiar with.

Thanks!

EDIT:

I posted the code here:

-(void)createSceneContents {
    self.spawningSpeed = 2.5;
self.enemySpawnTimer = [NSTimer scheduledTimerWithTimeInterval:self.spawningSpeed
                                                        target:self
                                                      selector:@selector(spawnObject)
                                                      userInfo:nil
                                                       repeats:YES];
}

There are more things in the createSceneContents method but those aren't important now.

-(void)spawnObject {
if (self.isPaused == NO){


        self.enemyData = [[Enemy alloc]init];

    self.aNewEnemy = [self.enemyData createEnemyWithSize:self.playerSize andWidth:self.frame.size.width andHeight:self.frame.size.height + self.player.position.y];
        self.aNewEnemy.physicsBody.allowsRotation = NO;
        self.aNewEnemy.physicsBody.categoryBitMask = self.enemyCategory;
        self.aNewEnemy.physicsBody.contactTestBitMask = self.enemyCategory | self.playerCategory | self.edgeCategory | self.bottomCategory;
        [self.world addChild:self.aNewEnemy];

    self.playerScore += 10;
    NSString *score = [NSString stringWithFormat:@"%i", self.playerScore];
    self.actualScore.text = score;

 }
}

In Enemy.m :

-(SKSpriteNode *)createEnemyWithSize:(float)size andWidth:(float)width andHeight:(float)height {
    self.enemy = [SKSpriteNode spriteNodeWithImageNamed:@"block.png"];
    self.enemy.size = CGSizeMake(size - 5, size - 5);

    self.enemy.name = @"fallingEnemy";
    self.enemy.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:CGSizeMake(size - 1, size - 1)];
    self.enemy.physicsBody.restitution = 0;
    int randomSection = arc4random_uniform(7);
    switch (randomSection) {
    case 0:

        self.enemy.position = CGPointMake(2.5 + self.enemy.size.width/2, height-5);

        break;
    case 1:


        self.enemy.position = CGPointMake(width/7 + self.enemy.size.width/2, height-5);

        break;
    case 2:

        self.enemy.position = CGPointMake((width/7*2)  + self.enemy.size.width/2, height-5);

        break;
    case 3:

        self.enemy.position = CGPointMake((width/7*3)  + self.enemy.size.width/2, height-5);

        break;
    case 4:

        self.enemy.position = CGPointMake((width/7*4)  + self.enemy.size.width/2, height-5);

        break;
    case 5:

        self.enemy.position = CGPointMake((width/7*5)  + self.enemy.size.width/2, height-5);

        break;
    case 6:

        self.enemy.position = CGPointMake((width/7*6)  + self.enemy.size.width/2, height-5);


        break;
    default:

        break;
 }
 return self.enemy;
}

This gets called in the didBeginContact when the enemy touches the ground or another enemy:

-(void)changeState {

   self.enemy.physicsBody.dynamic = NO;
   self.isFalling = NO;
   self.enemy.name = @"staticEnemy";

}

Now how do I keep track of individual enemies in the GameScene?

SemAllush
  • 477
  • 8
  • 16

1 Answers1

1

SpriteKit provides multiple ways to access nodes in the scene (e.g., nodeAtPoint, childNodeWithName, objectForKeyedSubscript, and enumerateChildNodesWithName), so there's no need to use properties/ivars to keep track of the nodes for most circumstances.

Specifically, you can determine if an enemy was involved in a contact event (in didBeginContact) by checking the categoryBitMask property of bodyA and bodyB. You can then use the body's node property to access the sprite node, and use the sprite node to change the enemy's name to @"staticEnemy" and unset the "ground" bit in the body's contactTestBitMask so it no longer triggers a contact event with the ground.

0x141E
  • 12,613
  • 2
  • 41
  • 54
  • But how do I affect 1 enemy without affecting other enemies in the scene – SemAllush Jan 01 '15 at 13:53
  • How do you want to affect the enemy? You can make your game event driven, where it reactions to various events. For example, when the timer triggers, you add an enemy to the scene (just add it to the scene and don't need to keep track of it with self.enemy). When a contact is made, you determine which enemy was involved and change it to be static. – 0x141E Jan 01 '15 at 17:41