【问题标题】:Stop an action that runs forever, run another acton and resume the stopped action in SpriteKit停止一个永远运行的动作,运行另一个动作并在 SpriteKit 中恢复停止的动作
【发布时间】:2020-08-05 04:53:23
【问题描述】:

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

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

但是,当我触摸屏幕时,恐龙确实会跳跃,但纹理并没有改变,它会继续行走。

我尝试了各种解决方案,例如结合 removeAction 和 run,将 moveSpeed 设置为 0 和 1,并在 touchesBegan 中简单地运行跳转序列,而无需任何其他设置,但上述方法均无效。

我的同学告诉我使用 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")
        }
    }

【问题讨论】:

    标签: ios asynchronous sprite-kit skaction


    【解决方案1】:

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

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

    要访问 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")
        }
    }
    

    【讨论】:

    • 完美运行!谢谢你,我会记住这一点的。
    • 很高兴它对您有所帮助。因为你是新人,所以我会让你知道,如果你觉得我的回答有帮助,你可以用箭头标记它。如果它也回答了您的问题,请检查标记为正确
    猜你喜欢
    • 1970-01-01
    • 2016-06-02
    • 1970-01-01
    • 2020-05-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-30
    • 2014-11-11
    相关资源
    最近更新 更多