Search code examples
ios7sprite-kit

A camera shake effect for SpriteKit


Does anyone know some out of the box libraries that might provide effects such as camera shake to an SKNode?

If not is there an easy way to implement a camera shake using actions?

Thanks


Solution

  • I found an elegant method using SKAction, that make shake your node. For example, with an horizontal shake:

    -(void)shake:(NSInteger)times {
        CGPoint initialPoint = self.position;
        NSInteger amplitudeX = 32;
        NSInteger amplitudeY = 2;
        NSMutableArray * randomActions = [NSMutableArray array];
        for (int i=0; i<times; i++) {
            NSInteger randX = self.position.x+arc4random() % amplitudeX - amplitudeX/2;
            NSInteger randY = self.position.y+arc4random() % amplitudeY - amplitudeY/2;
            SKAction *action = [SKAction moveTo:CGPointMake(randX, randY) duration:0.01];
            [randomActions addObject:action];
        }
        
        SKAction *rep = [SKAction sequence:randomActions];
        
        [self runAction:rep completion:^{
            self.position = initialPoint;
        }];
    }
    

    EDIT:

    Almost 10 years later, I came accross this request and found my own anwer. But now we have a new language, so let's translate it!

    extension SKNode {
        func shake(times: Int, amplitude: CGSize, duration: TimeInterval, completion: @escaping () -> Void) {
            guard times > 0 else { return }
            let initialPosition = self.position
            var randomActions: [SKAction] = []
            let stepDuration = duration / Double(times)
            for _ in 0..<times {
                let randX = self.position.x + CGFloat(arc4random_uniform(UInt32(amplitude.width))) - amplitude.width/2
                let randY = self.position.y + CGFloat(arc4random_uniform(UInt32(amplitude.height))) - amplitude.height/2
                randomActions.append(
                    SKAction.move(to: CGPoint(x: randX, y: randY), duration: stepDuration)
                )
            }
            self.run(SKAction.sequence(randomActions)) {
                self.position = initialPosition
                completion()
            }
        }
    }