Hallo Zusammen,
in meiner App Line Duel wackelt das gesamte Spielfeld, wenn einer der Spieler einen Unfall baut. Natürlich untermauert mit einer schönen SpriteKit Explosion. Heute zeige ich euch wie man soetwas programmiert.
Wir starten mit einem neuen Sprite Kit Projekt. Färben wir den Hintergrund ein und platzieren ein paar Bilder an zufälligen Positionen, damit der Explosions Effekt so richtig zur Geltung kommt. Ich nutzte dafür einfach das Spaceship, dass bei jedem neuen Projekt automatisch vorhanden ist. In didMoveToView:
self.backgroundColor = [SKColor darkGrayColor]; for (int i = 0; i <= 5; i++) { int x = self.view.frame.size.width; int y = self.view.frame.size.height; int randX = arc4random()%x; int randY = arc4random()%y; CGPoint dropPos = CGPointMake(randX, randY); SKSpriteNode *sprite = [SKSpriteNode spriteNodeWithImageNamed:@"Spaceship"]; sprite.xScale = 0.25; sprite.yScale = 0.25; sprite.position = dropPos; [self addChild:sprite]; }
Wir brauchen noch Partikel Effekte in Form von SKEmitterNodes. Definieren wir diese zunächst als propertys. Ihr könnt euch entweder über File > New > Ressource > SpriteKit Particle File eigene Emitter definieren oder ihr nutzt meine.
@property(strong, nonatomic) SKEmitterNode *smokeEmitter; @property(strong, nonatomic) SKEmitterNode *sparkEmitter;
Außerdem hat es sich aus meiner Sicht bewährt die Emitter initial zu laden und dann Kopien davon ablaufen zu lassen.
-(void)preloadParticle { NSString *path = [[NSBundle mainBundle] pathForResource:@"smoke" ofType:@"sks"]; self.smokeEmitter = [NSKeyedUnarchiver unarchiveObjectWithFile:path]; path = [[NSBundle mainBundle] pathForResource:@"spark" ofType:@"sks"]; self.sparkEmitter = [NSKeyedUnarchiver unarchiveObjectWithFile:path]; }
Nun ergänzen wir unsere ExplosionsMethode.
-(void)explosionAtPos:(CGPoint)pos { // add the spark emitter SKEmitterNode *emitterCopy = [self.sparkEmitter copy]; emitterCopy.position = pos; [self addChild:emitterCopy]; [emitterCopy runAction:[SKAction sequence:@[[SKAction waitForDuration:0.1], [SKAction scaleBy:1.5 duration:0.1], [SKAction runBlock:^ { emitterCopy.particleBirthRate = 0; [SKAction waitForDuration:0.1]; [SKAction runBlock:^ { [emitterCopy removeFromParent]; }]; }]]]]; // add the smoke emitter SKEmitterNode *smokeEmitterCopy = [self.smokeEmitter copy]; smokeEmitterCopy.position = pos; [self addChild:smokeEmitterCopy]; [smokeEmitterCopy runAction:[SKAction sequence:@[[SKAction waitForDuration:0.1], [SKAction scaleBy:1.2 duration:0.1], [SKAction runBlock:^ { smokeEmitterCopy.particleBirthRate = 0; [SKAction waitForDuration:0.1]; [SKAction runBlock:^ { [smokeEmitterCopy removeFromParent]; }]; }]]]]; }
Wir machen je eine Kopie der Emitter und setzten sie auf die übergebene Position. Anschließend starten ein paar SKActions, welche die Emitter etwas vergrößern. Kurz darauf wird der Emitter dann entfernt – aufräumen ist wichtig!
Für dieses Tutorial erstellen wir eine Explosion bei jedem touch.
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { UITouch *touch = [touches anyObject]; CGPoint positionInScene = [touch locationInNode:self]; [self explosionAtPos:positionInScene]; }
Das sieht dann schon ganz gut aus. Allerdings fehlt noch etwas Pfiff. Eine echte Explosion lässt den Boden erzittern. shakeScene wird bei jeder Explosion zusätzlich aufgerufen.
-(void)shakeScene { //pulsate the background [self runAction:[SKAction scaleTo:1.05 duration:0.05] completion:^{ [self runAction:[SKAction scaleTo:1 duration:0.05]]; }]; //animate quake, shake the scene SKAction* moveX_1 = [SKAction moveBy:CGVectorMake(-7, 0) duration:0.05]; SKAction* moveX_2 = [SKAction moveBy:CGVectorMake(-10, 0) duration:0.05]; SKAction* moveX_3 = [SKAction moveBy:CGVectorMake(7, 0) duration:0.05]; SKAction* moveX_4 = [SKAction moveBy:CGVectorMake(10, 0) duration:0.05]; SKAction* moveY_1 = [SKAction moveBy:CGVectorMake(-0, -7) duration:0.05]; SKAction* moveY_2 = [SKAction moveBy:CGVectorMake(0, -10) duration:0.05]; SKAction* moveY_3 = [SKAction moveBy:CGVectorMake(0, 7) duration:0.05]; SKAction* moveY_4 = [SKAction moveBy:CGVectorMake(0, 10) duration:0.05]; SKAction* trembleX = [SKAction sequence:@[moveX_1, moveX_4, moveX_2, moveX_3]]; SKAction* trembleY = [SKAction sequence:@[moveY_1, moveY_4, moveY_2, moveY_3]]; for (SKNode *child in self.children) { [child runAction:trembleX]; [child runAction:trembleY]; } }
Bis bald.