Adam Carter
Adam Carter

Reputation: 4844

iOS - Adding ‘explosion’ effect (which breaks Sprite in to little pieces and then fall) to sprite in SpriteKit

I want to apply the same effect to a number of different sprites in my iOS game so am looking in to a general approach rather than an animation created in another program and using its images to create a UIImageView animation.

This effect is an ‘explosion’ type animation where my sprite’s image gets chopped in to different pieces, then, using the physics engine, those pieces get exploded out in different directions before falling down.

I’m new to SpriteKit, but am assuming I have to do this in Quartz? Then re-add the new images as sprites and apply the animation?

I don’t really know where to start, let alone how to continue with the rest of the steps.

Does anyone have any ideas?

Thanks.

Upvotes: 3

Views: 2127

Answers (1)

BenJammin
BenJammin

Reputation: 1467

1) Upon initialization of said exploding object, first we create a SKTextureAtlas which holds all of the images being animated. You must have the texture atlas resources available.

2) Load all of the relevant SKTextures into an array. This array should be private to the object to which the explosion is happening. A safe way to do this:

- (void)loadContactImages {
     NSMutableArray *frames = [NSMutableArray array];
     SKTextureAtlas *explosionFrames = [SKTextureAtlas atlasNamed:@"explosionFrames"];
     for(int i = 0; i < explosionFrames.textureNames.count; i++) {
          NSString *textureName = [NSString stringWithFormat:@"explosionFrame_%d" , i]; 
          SKTexture *texture = [explosionFrames textureNamed:textureName];
          if(texture) {
              [frames addObject:texture];
         }
    }
    self.contactFrames = frames;
}

3) You will then define a method which will animate the explosion. Look into the SKAction header for more info. Plug in time per frame that makes sense to your explosion

- (SKAction *)runExplosion {
    return [SKAction animateWithTextures:self.contactFrames timePerFrame:0.1];     
}

4) As for the exploding pieces, you should preload them, so to limit the overhead of sending the pieces into random directions (with this we won't have the extra overhead of creating all those new sprites at the time of the explosion). Don't forget to give them physics bodies (SKPhysicsBody) and set the isAffectedByGravity property to YES!

- (SKAction *)explosionOfPieces {
     return [SKAction runBlock:^ {
         for(SKSpriteNode *piece in self.explodingPieces)   {
              piece.hidden = NO;
              piece.position = self.position;
              [self addChild:piece];
              [piece.physicsBody applyImpulse:CGVectorMake(dx , dy)]; //specify the direction here
          }
     }];
}

5) Bringing it all together, expose a method to return a sequence of these actions. If you would like to have these two actions occur together, there is also a class method on SKAction called [SKAction group: (NSArray *)]

- (void)explosionSequence {
     [self runAction: [SKAction sequence:@[ [self runExplosion] , [self explosionOfPieces]]]];
}

Note: Physics reactions occur in SKScene's. We expose this action so the scene can run it on your object within the scene. You will also want to conform to a protocol called SKPhysicsContactDelegate within your scene and call:

[myExplodingObject explosionSequence];

within the delegate method:

- (void)didBeginContact:(SKPhysicsContact *)contact

Within this SKPhysicsContact object lie two colliding bodies. Both of these bodies ("exploding object" and "explosion trigger") must have their SKPhysicsBody property initialized and their contactTestBitMask property set (so this object knows what it can collide with). I would also set the categoryBitMask property so we can directly introspect the bodies' type. We reference these colliding bodies like this:

- (void)didBeginContact:(SKPhysicsContact *)contact {
     if(contact.bodyA.categoryBitMask == explodingObjectCategory && contact.bodyB.categoryBitMask == explodingTriggerCategory) {
          [self.myExplodingObject explosionSequence];
     }
}

Please look into Apple's docs for more info.

Upvotes: 3

Related Questions