Mar*_*tin 15
我找到了一种使用SKAction的优雅方法,可以让你的节点震动.例如,水平摇晃:
-(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;
}];
}
Run Code Online (Sandbox Code Playgroud)
Ben*_*nzi 13
接受的答案中的摇动方法有一个警告 - 它只能应用于没有x,y坐标被其他正在运行的SKAction修改的节点.这是因为我们在摇动完成后将节点的位置重置为其初始位置.
如果你想要一个同样适用于其他SKAction的摇动动作,它可以按顺序/并行方式修改摇动节点的位置(x或y坐标),你需要添加你正在应用的随机摇动的反向动作.
Swift扩展名供参考:
extension SKAction {
class func shake(duration:CGFloat, amplitudeX:Int = 3, amplitudeY:Int = 3) -> SKAction {
let numberOfShakes = duration / 0.015 / 2.0
var actionsArray:[SKAction] = []
for index in 1...Int(numberOfShakes) {
let dx = CGFloat(arc4random_uniform(UInt32(amplitudeX))) - CGFloat(amplitudeX / 2)
let dy = CGFloat(arc4random_uniform(UInt32(amplitudeY))) - CGFloat(amplitudeY / 2)
let forward = SKAction.moveByX(dx, y:dy, duration: 0.015)
let reverse = forward.reversedAction()
actionsArray.append(forward)
actionsArray.append(reverse)
}
return SKAction.sequence(actionsArray)
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,此修改不要求将节点作为参数传入
如果您已经使用Swift,可以使用以下代码...
let shake = SKAction.shake(node.position, duration: 0.3)
node.runAction(shake)
Run Code Online (Sandbox Code Playgroud)
或者对于更强烈的震动,您也可以配置振幅
let shake = SKAction.shake(node.position, duration: 0.3, amplitudeX: 12, amplitudeY: 3)
node.runAction(shake)
Run Code Online (Sandbox Code Playgroud)
这是扩展....
extension SKAction {
class func shake(initialPosition:CGPoint, duration:Float, amplitudeX:Int = 12, amplitudeY:Int = 3) -> SKAction {
let startingX = initialPosition.x
let startingY = initialPosition.y
let numberOfShakes = duration / 0.015
var actionsArray:[SKAction] = []
for index in 1...Int(numberOfShakes) {
let newXPos = startingX + CGFloat(arc4random_uniform(UInt32(amplitudeX))) - CGFloat(amplitudeX / 2)
let newYPos = startingY + CGFloat(arc4random_uniform(UInt32(amplitudeY))) - CGFloat(amplitudeY / 2)
actionsArray.append(SKAction.moveTo(CGPointMake(newXPos, newYPos), duration: 0.015))
}
actionsArray.append(SKAction.moveTo(initialPosition, duration: 0.015))
return SKAction.sequence(actionsArray)
}
}
Run Code Online (Sandbox Code Playgroud)
积分转到Stephen Haney实施我刚刚将其转移到扩展中
如果你想动摇整个场景,这里是 Rob 用 Swift 写的答案的一个版本:
func sceneShake(shakeCount: Int, intensity: CGVector, shakeDuration: Double) {
let sceneView = self.scene!.view! as UIView
let shakeAnimation = CABasicAnimation(keyPath: "position")
shakeAnimation.duration = shakeDuration / Double(shakeCount)
shakeAnimation.repeatCount = Float(shakeCount)
shakeAnimation.autoreverses = true
shakeAnimation.fromValue = NSValue(cgPoint: CGPoint(x: sceneView.center.x - intensity.dx, y: sceneView.center.y - intensity.dy))
shakeAnimation.toValue = NSValue(cgPoint: CGPoint(x: sceneView.center.x + intensity.dx, y: sceneView.center.y + intensity.dy))
sceneView.layer.add(shakeAnimation, forKey: "position")
}
Run Code Online (Sandbox Code Playgroud)
我将此函数包含在 SKScene 子类中。这是一个示例调用:
sceneShake(shakeCount: 3, intensity: CGVector(dx: shakeIntensity, dy: shakeIntensity), shakeDuration: shakeDuration)
Run Code Online (Sandbox Code Playgroud)