Reputation: 4844
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
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 SKTexture
s 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