Douglas
Douglas

Reputation: 2524

Sprite Kit, make multiple sprites obey same method

I am working on a sprite kit game for the iPhone were there is a player, and 12 "enemies". Each of these enemies is created the same way. I did this with a for loop in the initWithSize method.

for (int i = 1; i <= 12; i++)
    {
        [self spawnChargesWithNumber:i];
    }

The actual method that makes the enemies (spawnChargesWithNumber) is as follows.

- (void)spawnChargesWithNumber:(NSInteger)number
{

self.chargedBall = [[ChargedBall alloc] initWithImageNamed:[NSString stringWithFormat:@"ChargedBall%li", (long)number]];
int minX = self.chargedBall.size.width / 2;
int maxX = self.frame.size.width - self.chargedBall.size.width/2;
int rangeX = maxX - minX;
int actualX = (arc4random() % rangeX) + minX;

self.chargedBall.position = CGPointMake(actualX, 568);
self.chargedBall.name = [NSString stringWithFormat:@"chargeNumber%li", (long)number];
self.chargedBall.zPosition = 15;
self.chargedBall.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:13.0f];
self.chargedBall.physicsBody.dynamic = YES;
self.chargedBall.physicsBody.affectedByGravity = NO;
self.chargedBall.physicsBody.mass = 0.1;
[self.map addChild:self.chargedBall];
}

This does actually create 12 different enemies, but only the last one is actually a chargedBall object. I have an object called ChargedBall where there is a .h and .m file. In the .m file I have a method to update where the object is.

In the update:currentTime method I call this method to update where the ball is, and I check for collisions with the tileMap in this method as well.

-(void)update:(CFTimeInterval)currentTime
{

NSTimeInterval delta = currentTime - self.previousUpdateTime;

if (delta > 0.02)
{
    delta = 0.02;
}

self.previousUpdateTime = currentTime;
[self.player update:delta];
[self.chargedBall update:delta];
[self checkForAndResolveCollisionsForPlayer:self.player forLayer:self.walls];
[self checkForAndResolveCollisionsForCharge:self.chargedBall forLayer:self.walls];
[self processUserMotionForUpdate:currentTime];
[self setViewPointCenter:self.player.position];
}

This works very well if I only have one enemy/chargedBall. If I have multiple chargedBalls then only the last one behave the way it should. The others just stay on the screen. I think this has to do with how I make the chargedBall. I recreate the chargedBall object each time, so that only the last one is actually a chargedBall, not the others because I overwrite them. So my ultimate question is, how can I have all enemies/chargedBall object behave the same way and follow the same method to update themselves? Thanks so much for any and all your help

Upvotes: 1

Views: 653

Answers (2)

Rafał Sroka
Rafał Sroka

Reputation: 40030

Store all your ChargedBall objects in an array. Declare a property:

@property (nonatomic, strong) NSMutableArray *enemies.

Every time you create an enemy, add it to the enemies array.

- (void)spawnChargesWithNumber:(NSInteger)number
{
    ChargedBall *enemy = [[ChargedBall alloc] ...];

    // Your code ...

    if (!_enemies)
    {
        _enemies = [[NSMutableArray alloc] init];
    }

    [_enemies addObject:enemy];
}

Then for each ChargedBall in array update it in update method:

for(ChargedBall *enemy in self.enemies)
{
    [self checkForAndResolveCollisionsForCharge:enemy forLayer:self.walls];
}

Side note:

This does not apply to this question but it's nice to know. If you wanted to call a method of each enemy, you could do it in one line using NSArray's makeObjectsPerformSelector: method. Example:

[_enemies makeObjectsPerformSelector:@selector(selfDestruct)];

Upvotes: 3

jervine10
jervine10

Reputation: 3077

You have a property defined for your chargedBall, however you need a mutable array. Define a property to house all of the balls. Something like this:

@property (nonatomic, strong) NSMutableArray *chargedBalls.

Then change your for loop to this (make sure you've initialized the array somewhere):

- (void)spawnChargesWithNumber:(NSInteger)number
{

   ChargedBall *chargedBall = [[ChargedBall alloc] initWithImageNamed:[NSString stringWithFormat:@"ChargedBall%li", (long)number]];
   int minX = chargedBall.size.width / 2;
   int maxX = self.frame.size.width - chargedBall.size.width/2;
   int rangeX = maxX - minX;
   int actualX = (arc4random() % rangeX) + minX;

   chargedBall.position = CGPointMake(actualX, 568);
   chargedBall.name = [NSString stringWithFormat:@"chargeNumber%li", (long)number];
   chargedBall.zPosition = 15;
   chargedBall.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:13.0f];
   chargedBall.physicsBody.dynamic = YES;
   chargedBall.physicsBody.affectedByGravity = NO;
   chargedBall.physicsBody.mass = 0.1;
   [self.map addChild:chargedBall];

   [self.chargedBalls addObject:chargedBall];
}

Then you can iterate the array and determine if there is a collision with any of the balls. However if you're using SpriteKit's physics engine you can have the engine itself notify you of collisions.

Upvotes: 1

Related Questions