Остановите действие, которое выполняется навсегда, запустите другой актон и возобновите остановленное действие в SpriteKit. - PullRequest
0 голосов
/ 22 апреля 2020

Я реплицирую игру 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")
        }
    }

1 Ответ

0 голосов
/ 22 апреля 2020

SKActions в Spritekit имеют встроенный обработчик завершения при запуске. так что нет необходимости отправлять очередь.

Я разбил действия на переменные для облегчения чтения, и, по моему мнению, переход вниз должен быть быстрее, чем прыжок вверх

, чтобы получить доступ к завершению 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")
    }
}
...