swift - 为 SpriteKit 创建按钮

标签 swift sprite-kit

我正在为我正在构建的 sprite 工具包应用程序创建主菜单。在我的整个项目中,我一直使用 SKScenes 来保存我的关卡和实际游戏玩法。但是,现在我需要一个主菜单,其中包含“播放”、“级别”、“商店”等按钮...但是,我现在添加按钮的方式让我感觉不太舒服,就像这样:

let currentButton = SKSpriteNode(imageNamed: button)  // Create the SKSpriteNode that holds the button

self.addChild(currentButton) // Add that SKSpriteNode to the SKScene

然后我像这样检查按钮的触摸:

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    let touch = touches.first
    let touchLocation = touch!.location(in: self)

    for node in self.nodes(at: touchLocation) {
        guard let nodeName = node.name else {
            continue
        }
        if nodeName == ButtonLabel.Play.rawValue {
            DispatchQueue.main.asyncAfter(deadline: .now()) {
                let transition = SKTransition.reveal(with: .left, duration: 1)
                self.view?.presentScene(self.initialLevel, transition: transition)
                self.initialLevel.loadStartingLevel()
            }
            return
        }
        if nodeName == ButtonLabel.Levels.rawValue {
            slideOut()
        }

    }
}

但是,我不知道这样算不算高效。 我正在考虑改用 UIButton,但为此我必须使用 UIView 吗?

或者我可以将 UIButtons 添加到 SKView (我真的不明白 SKView、SKScene 和 UIView 之间的区别) 菜单推荐什么?

最佳答案

我完全同意@Whirlwind 的观点,为您的按钮创建一个单独的类来为您处理工作。我不认为@ElTomato 的建议是正确的建议。如果您创建一个包含按钮的图像,那么您在这些按钮的位置、大小、外观和按钮状态方面没有灵 active 。

这是一个非常简单的按钮类,它是 SKSpriteNode 的子类。它使用委托(delegate)将信息发送回父级(例如哪个按钮已被按下),并为您提供简单的状态更改(单击时变小,释放时恢复正常大小)

import Foundation
import SpriteKit

protocol ButtonDelegate: class {
    func buttonClicked(sender: Button)
}

class Button: SKSpriteNode {

    //weak so that you don't create a strong circular reference with the parent
    weak var delegate: ButtonDelegate!

    override init(texture: SKTexture?, color: SKColor, size: CGSize) {

        super.init(texture: texture, color: color, size: size)

        setup()
    }

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

        setup()
    }

    func setup() {
        isUserInteractionEnabled = true
    }

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        setScale(0.9)
        self.delegate.buttonClicked(sender: self)
    }

    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        setScale(1.0)
    }
}

这个按钮可以用两种方式实例化。您可以在场景编辑器中创建它的一个实例,或在代码中创建一个实例。

creating the button in Scene editor

class MenuScene: SKScene, ButtonDelegate {

    private var button = Button()

    override func didMove(to view: SKView) {

        if let button = self.childNode(withName: "button") as? Button {
            self.button = button
            button.delegate = self
        }

        let button2 = Button(texture: nil, color: .magenta, size: CGSize(width: 200, height: 100))
        button2.name = "button2"
        button2.position = CGPoint(x: 0, y: 300)
        button2.delegate = self
        addChild(button2)
    }
}

func buttonClicked(sender: Button) {
    print("you clicked the button named \(sender.name!)")
}

You have to remember to make the scene conform to the delegate

class MenuScene: SKScene, ButtonDelegate

func buttonClicked(sender: Button) {
    print("you clicked the button named \(sender.name!)")
}

关于swift - 为 SpriteKit 创建按钮,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44415145/

相关文章:

swift - 关闭父 View Controller

ios - 周数的 UIDatePicker

ios - 如何使用 Firebase 获取通知响应数据?

swift - 如何移动 SKNode?

ios - SpriteKit 中没有任何内容出现在场景中

ios - 使用 swift 我试图获取电话号码标签数组中特定标签的索引值

swift - 使用 NSDateComponents 时无法获取返回的目标日期

swift - 在后台线程中运行 SpriteKit 进程以提高 CPU 使用率

ios - 从应用程序委托(delegate)暂停场景时 Spritekit 游戏崩溃

ios - SKView CALayer 上方的 SpriteKitNode