永远停止 运行s 的动作,运行 另一个动作并恢复 SpriteKit 中停止的动作

Stop an action that runs forever, run another acton and resume the stopped action in SpriteKit

我正在为一个 class 项目复制 Chrome 恐龙游戏,但我 运行 遇到了一个问题,我很难从 运行 中阻止恐龙当它跳跃时。

我在 SKTextureAtlas 中有三个纹理:walk_1、walk_2 和跳跃,我希望恐龙在 walk_1 和 walk_2 之间不断切换,所以它看起来就像在走路一样。当我触摸屏幕时,恐龙跳跃,停止行走,纹理设置为跳跃,直到它再次落在地上,然后再次开始行走。

然而,当我触摸屏幕时,恐龙确实跳了,但纹理没有改变,它一直在走。

我已经尝试了各种解决方案,例如组合 removeAction 和 运行,将 moveSpeed 设置为 0 和 1 并简单地 运行 在 touchesBegan 中设置跳转序列而没有任何其他设置,但是 none 以上作品。

我的 class 朋友告诉我使用 DispatchQueue.main.asyncAfter,令人惊讶的是,它有效!但我不太清楚为什么它会起作用,想知道是否有任何其他解决方案可以实现相同的目标。

import SpriteKit

class GameScene: SKScene {

    var dinoTexture:SKTextureAtlas!
    var dinosaur:SKSpriteNode!
    var walkForever:SKAction!

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

    override init(size: CGSize) {
        super.init(size: size)
        dinoTexture = SKTextureAtlas(named: "dinosaur")
    }

    override func didMove(to view: SKView) {

        let walkOnce = SKAction.animate(with: [dinoTexture.textureNamed("walk_1.png"), dinoTexture.textureNamed("walk_2.png")], timePerFrame: 0.1)
        walkForever = SKAction.repeatForever(walkOnce)

        dinosaur = SKSpriteNode(texture: dinoTexture.textureNamed("walk_2.png"))

        dinosaur.run(walkForever, withKey: "dinosaurWalk")

        self.addChild(dinosaur)
    }

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
            dinosaur.removeAction(forKey: "dinosaurWalk")
            dinosaur.run(SKAction.sequence([SKAction.setTexture(dinoTexture.textureNamed("jump.png")), SKAction.moveBy(x: 0, y: 150, duration: 0.5), SKAction.moveBy(x: 0, y: -150, duration: 0.5), SKAction.setTexture(dinoTexture.textureNamed("walk_2.png"))]))
            DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
                self.dinosaur.run(self.walkForever, withKey: "dinosaurWalk")
        }
    }

Spritekit 中的 SKActions 在 运行 时有一个内置的完成处理程序。所以不需要调度队列。

为了便于阅读,我将动作分解为变量,而且我认为向下跳应该比向上跳快

要访问 SKAction 的完成,请将您的后续代码放在 运行 命令后的波浪括号中

self.run(someAction) {
    //run some code after someAction has run
}

您只需

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {

    coco.removeAction(forKey: "cocoWalk")

    let setJumpTexture = SKAction.setTexture(SKTexture(imageNamed: "coco_jump.png"))
    let setWalkTexture = SKAction.setTexture(SKTexture(imageNamed: "coco_walk2.png"))
    let jumpUp = SKAction.moveBy(x: 0, y: 150, duration: 0.5)
    let jumpDown = SKAction.moveBy(x: 0, y: -150, duration: 0.25)

    coco.run(SKAction.sequence([setJumpTexture, jumpUp, jumpDown, setWalkTexture])) {
        self.coco.run(self.walkForever, withKey: "cocoWalk")
    }
}