【问题标题】:How to go back to the previous scene after tapping a colour sprite in swift?快速点击颜色精灵后如何返回上一个场景?
【发布时间】:2017-05-19 21:36:30
【问题描述】:

所以对于一个学校项目,我的任务是制作一个 2D 游戏。游戏很好,但我正在努力制作一个后退按钮(在页面中间),所以想知道是否有特定的代码可以完成这项工作。我正在使用 spriteKit,所以我试图在单击颜色精灵后返回上一个场景。

如果这是一个愚蠢的问题,我深表歉意,但我对 Swift 有点陌生。

亲切的问候, 詹姆斯

【问题讨论】:

标签: ios swift button sprite-kit scene


【解决方案1】:

这是一个如何使用彩色精灵创建按钮的示例。它展示了如何设置按钮来接收触摸事件以及如何使用这些触摸事件在场景之间导航。

在此示例中,您可以向前导航到新场景并向后导航到以前的场景。

import SpriteKit

class Button: SKSpriteNode {

    var tapped: (() -> Void)?

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

}

class GameScene: SKScene {

    var parentScene: SKScene?
    var sceneCount = 1

    override func didMove(to view: SKView) {
        if parentScene != nil {
            let backButton = addButton(color: .red, position: CGPoint(x: -200, y: 0))
            backButton.tapped = {
                if let previousScene = self.parentScene {
                    view.presentScene(previousScene)
                }
            }
        }

        let nextButton = addButton(color: .blue, position: CGPoint(x: 200, y: 0))
        nextButton.tapped = {
            if let nextScene = SKScene(fileNamed: "GameScene") as? GameScene {
                nextScene.scaleMode = self.scaleMode
                nextScene.parentScene = self
                nextScene.sceneCount = self.sceneCount + 1
                view.presentScene(nextScene)
            }
        }

        let label = SKLabelNode(text: "Scene \(sceneCount)")
        addChild(label)
    }

    func addButton(color: SKColor = .white, position: CGPoint = .zero) -> Button {
        let button = Button(color: color, size: CGSize(width: 200, height: 200))
        button.position = position
        button.isUserInteractionEnabled = true
        addChild(button)
        return button
    }

}

【讨论】:

    【解决方案2】:

    添加按钮最简单的方法是在相关的 SKScene 中检测您的精灵的触摸。

    enum NodeName: String {
       case coloredSprite1
       case coloredSprite2
    }
    
    class GameScene: SKScene {
    
         let coloredSprite = SKSpriteNode(imageNamed: "YourImageName")
    
         /// Scene setup
         override func didMove(to view: SKView) {
           // set up your colored sprite if necessary
           // Give your sprites unique names to identify them
    
           coloredSprite.name = NodeName.coloredSprite1.rawValue // always use enums for things like string identifiers so you avoid typos
         }
    
         /// Touches
         override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
             for touch in touches {
                 let location = touch.location(in: self)
                 let touchedNode = atPoint(location)
    
                 // Way 1 by node (probably less preferable)
                 switch touchedNode {
                 case coloredSprite:
                     // do something (e.g call loadScene method)
                    // see below
                 default: 
                     break
                 }
    
                 // Way 2 by node name (probably more preferable)
                 // name is an optional so we have to unwrap it when using it in the switch statement. 
                 // The easiest way is by providing an alternative string, by using the nil coalescing operator (?? "NoNodeNameFound")
    
                 switch touchedNode.name ?? "NoNodeNameFound" {
                 case NodeName.coloredSprite1.rawValue:
                    // do something (e.g call loadScene method)
                    // see below
                 default: 
                    break
                 }
            }
        }
    
        // Also call touchesEnded, touchesMoved and touchesCancelled and do necessary stuff
    }
    

    对于更可重用的解决方案,您最好创建一个按钮子类。谷歌有很多关于如何做到这一点的教程。

    为了在 SKScene 之间转换,您可以在每个场景中创建一个 loadScene 方法,然后在必要时调用它们。

    // Start Scene
    class StartScene: SKScene {
       ...
    
       func loadGameScene() {
    
            // If you do everything in code
            let gameScene = GameScene(size: self.size)
            view?.presentScene(gameScene, transition: ...)
    
            // If you use SpriteKit scene editor
            guard let gameScene = SKScene(fileNamed: "GameScene") else { return } // fileNamed is the name you gave the .sks file
            view?.presentScene(gameScene, transition: ...)
       }
    }
    
    // Game scene
    class GameScene: SKScene {
         ....
    
         func loadStartScene() {
            // If you do everything in code
            let startScene = StartScene(size: self.size)
            view?.presentScene(startScene, transition: ...)
    
            // If you use SpriteKit scene editor
            guard let startScene = SKScene(fileNamed: "StartScene") else { return } // fileNamed is the name you gave the .sks file
            view?.presentScene(startScene, transition: ...)
       }
    }
    

    希望对你有帮助

    【讨论】:

    • 我在回答中添加了更多细节,并附上了一个关于如何在 SpriteKit 中进行触摸的简单示例。
    • 再次感谢您的帮助,非常感谢!
    • 我现在正在让游戏场景在得分计数器达到 10 时返回菜单。它需要相同或相似的代码还是完全不同?跨度>
    • 基本相同的代码。您的代码中的某处会有一些逻辑,用于在每次增加时检查分数值。你可以检查它是否是 10,如果它是调用 loadScene 方法。
    • 不用担心。如果您遇到困难,请再问一个问题,我会尽力提供帮助。
    猜你喜欢
    • 1970-01-01
    • 2019-08-11
    • 2015-06-02
    • 1970-01-01
    • 1970-01-01
    • 2017-02-21
    • 2012-09-08
    • 1970-01-01
    • 2023-04-10
    相关资源
    最近更新 更多