在不禁用触摸的情况下完成 SpriteNode 上的操作 运行
Finish action running on a SpriteNode without disabling touches
我有一个玩家的 physicsBody 分为多个部分(躯干、腿、头等),现在我在屏幕上有一个控制玩家移动的按钮,如果向右按下按钮玩家向右移动,那部分工作正常。问题是每次运动改变时都会调用 walk() 方法,它所做的是让玩家的腿看起来像在走路,但如果运动没有停止,那么就会继续调用 walk() 而不会完成动画,所以它看起来像是来回卡住。我想要实现的是让玩家能够不断地行走,但是 walk() (动画方法)被调用一次,完成,然后再次调用(只要仍然按下行走按钮)。这是我目前所拥有的:
func walk(){
let leftFootWalk = SKAction.run {
let action = SKAction.moveBy(x: 1, y: 0.1, duration: 0.1)
let actionReversed = action.reversed()
let seq = SKAction.sequence([action, actionReversed])
self.leftUpperLeg.run(seq)
self.leftLowerLeg.run(seq)
}
let rightFootWalk = SKAction.run {
let action = SKAction.moveBy(x: 0.4, y: 0.1, duration: 0.1)
let actionReversed = action.reversed()
let seq = SKAction.sequence([action, actionReversed])
self.rightUpperLeg.run(seq)
self.rightLowerLeg.run(seq)
}
let group = SKAction.sequence([leftFootWalk, SKAction.wait(forDuration: 0.2), rightFootWalk])
run(group)
}
extension GameScene: InputControlProtocol {
func directionChangedWithMagnitude(position: CGPoint) {
if isPaused {
return
}
if let fighter = self.childNode(withName: "fighter") as? SKSpriteNode, let fighterPhysicsBody = fighter.physicsBody {
fighterPhysicsBody.velocity.dx = position.x * CGFloat(300)
walk()
if position.y > 0{
fighterPhysicsBody.applyImpulse(CGVector(dx: position.x * CGFloat(1200),dy: position.y * CGFloat(1200)))
}else{
print("DUCK") //TODO: duck animation
}
}
}
我能够解决这个问题,但是我仍然确定有更好的方法,所以如果您知道,请务必告知。这是我所做的:
首先,我添加了一个名为 isWalking 的布尔值,以了解行走动画是开启(真)还是关闭(假),并将其设置为假。然后我添加了 if 语句以仅在动画关闭(false)时调用 walk()并将布尔值设置为 on(true)。
func directionChangedWithMagnitude(position: CGPoint) {
if isPaused {
return
}
if let fighter = self.childNode(withName: "fighter") as? SKSpriteNode, let fighterPhysicsBody = fighter.physicsBody {
fighterPhysicsBody.velocity.dx = position.x * CGFloat(300)
print(fighterPhysicsBody.velocity.dx)
if !isWalking{
isWalking = true
walk()
}
}
}
并且我更改了 walk() 以使用完成块并再次将布尔值设置为 off(false)
func walk(){
let walkAction = SKAction.moveBy(x: 5, y: 5, duration: 0.05)
let walk = SKAction.sequence([walkAction, walkAction.reversed()])
leftUpperLeg.run(walk) {
self.rightUpperLeg.run(walk)
}
leftLowerLeg.run(walk) {
self.rightLowerLeg.run(walk, completion: {
self.isWalking = false
})
}
}
首先你可以使用SKAction.runBlock({ self.doSomething() })
作为动作序列中的最后一个动作,而不是使用完成。
关于你的问题,你可以使用hasAction
判断你的SKNode
目前是否运行任何动作,你可以使用key机制更好的进行动作管理
看下一个问答
checking if an SKNode is running a SKAction
我有一个玩家的 physicsBody 分为多个部分(躯干、腿、头等),现在我在屏幕上有一个控制玩家移动的按钮,如果向右按下按钮玩家向右移动,那部分工作正常。问题是每次运动改变时都会调用 walk() 方法,它所做的是让玩家的腿看起来像在走路,但如果运动没有停止,那么就会继续调用 walk() 而不会完成动画,所以它看起来像是来回卡住。我想要实现的是让玩家能够不断地行走,但是 walk() (动画方法)被调用一次,完成,然后再次调用(只要仍然按下行走按钮)。这是我目前所拥有的:
func walk(){
let leftFootWalk = SKAction.run {
let action = SKAction.moveBy(x: 1, y: 0.1, duration: 0.1)
let actionReversed = action.reversed()
let seq = SKAction.sequence([action, actionReversed])
self.leftUpperLeg.run(seq)
self.leftLowerLeg.run(seq)
}
let rightFootWalk = SKAction.run {
let action = SKAction.moveBy(x: 0.4, y: 0.1, duration: 0.1)
let actionReversed = action.reversed()
let seq = SKAction.sequence([action, actionReversed])
self.rightUpperLeg.run(seq)
self.rightLowerLeg.run(seq)
}
let group = SKAction.sequence([leftFootWalk, SKAction.wait(forDuration: 0.2), rightFootWalk])
run(group)
}
extension GameScene: InputControlProtocol {
func directionChangedWithMagnitude(position: CGPoint) {
if isPaused {
return
}
if let fighter = self.childNode(withName: "fighter") as? SKSpriteNode, let fighterPhysicsBody = fighter.physicsBody {
fighterPhysicsBody.velocity.dx = position.x * CGFloat(300)
walk()
if position.y > 0{
fighterPhysicsBody.applyImpulse(CGVector(dx: position.x * CGFloat(1200),dy: position.y * CGFloat(1200)))
}else{
print("DUCK") //TODO: duck animation
}
}
}
我能够解决这个问题,但是我仍然确定有更好的方法,所以如果您知道,请务必告知。这是我所做的: 首先,我添加了一个名为 isWalking 的布尔值,以了解行走动画是开启(真)还是关闭(假),并将其设置为假。然后我添加了 if 语句以仅在动画关闭(false)时调用 walk()并将布尔值设置为 on(true)。
func directionChangedWithMagnitude(position: CGPoint) {
if isPaused {
return
}
if let fighter = self.childNode(withName: "fighter") as? SKSpriteNode, let fighterPhysicsBody = fighter.physicsBody {
fighterPhysicsBody.velocity.dx = position.x * CGFloat(300)
print(fighterPhysicsBody.velocity.dx)
if !isWalking{
isWalking = true
walk()
}
}
}
并且我更改了 walk() 以使用完成块并再次将布尔值设置为 off(false)
func walk(){
let walkAction = SKAction.moveBy(x: 5, y: 5, duration: 0.05)
let walk = SKAction.sequence([walkAction, walkAction.reversed()])
leftUpperLeg.run(walk) {
self.rightUpperLeg.run(walk)
}
leftLowerLeg.run(walk) {
self.rightLowerLeg.run(walk, completion: {
self.isWalking = false
})
}
}
首先你可以使用SKAction.runBlock({ self.doSomething() })
作为动作序列中的最后一个动作,而不是使用完成。
关于你的问题,你可以使用hasAction
判断你的SKNode
目前是否运行任何动作,你可以使用key机制更好的进行动作管理
看下一个问答 checking if an SKNode is running a SKAction