简体   繁体   English

使用spritekit swift在swift中创建游戏主菜单

[英]Create a main menu for game in swift using spritekit swift

I am new to swift, and have an SKScene in which I have created a game. 我是swift的新手,并拥有一个SKScene,我在其中创建了一个游戏。 I can not seem to figure out however, how to build the menu. 我似乎无法弄清楚如何构建菜单。 If seen both solutions to create either another view controller or another SKScene but they were all quite confusing and complex. 如果看到两个解决方案创建另一个视图控制器或另一个SKScene,但它们都非常混乱和复杂。 I am open to use either of these methods or any other, does anyone have any tricks to tackle this problem. 我愿意使用这些方法或任何其他方法,有没有人有任何技巧来解决这个问题。 Some code would be helpful. 一些代码会有所帮助。 Thanks for the help. 谢谢您的帮助。

There are many ways to obtain a menu in Sprite-Kit . 有很多方法可以在Sprite-Kit中获取菜单。

Usually people draw some SKLabelNode , or SKSpriteNode to build menu voices or make a specific SKNode that build this kind of structure. 通常人们会绘制一些SKLabelNodeSKSpriteNode来构建菜单语音或制作构建此类结构的特定SKNode

But I want to follow a suggestion on comments about StackView . 但我想对有关StackView评论提出建议。 We know StackView is an UIKit element that: 我们知道StackView是一个UIKit元素:

Provides a streamlined interface for laying out a collection of views in either a column or a row. 提供简化的界面,用于在列或行中布置视图集合。

So , we can build a vertical StackView that contains all the menu voices (PS the code below show a simple collection of labels, you can customize your StackView views as you wish): 因此,我们可以构建一个包含所有菜单语音的垂直StackView (PS下面的代码显示了一个简单的标签集合,您可以根据需要自定义StackView视图):

import SpriteKit
import UIKit
protocol StackViewDelegate: class {
    func didTapOnView(at index: Int)
}
class GameMenuView: UIStackView {
    weak var delegate: StackViewDelegate?
    override init(frame: CGRect) {
        super.init(frame: frame)
        self.axis = .vertical
        self.distribution = .fillEqually
        self.alignment = .fill
        self.spacing = 5
        self.isUserInteractionEnabled = true
        //set up a label
        for i in 1...5 {
            let label = UILabel()
            label.text = "Menu voice \(i)"
            label.textColor = UIColor.white
            label.backgroundColor = UIColor.blue
            label.textAlignment = .center
            label.tag = i
            self.addArrangedSubview(label)
        }
        configureTapGestures()
    }
    required init(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    private func configureTapGestures() {
        arrangedSubviews.forEach { view in
            view.isUserInteractionEnabled = true
            let tapGesture = UITapGestureRecognizer(target: self, action: #selector(didTapOnView))
            view.addGestureRecognizer(tapGesture)
        }
    }
    func didTapOnView(_ gestureRecognizer: UIGestureRecognizer) {
        if let index = arrangedSubviews.index(of: gestureRecognizer.view!) {
            delegate?.didTapOnView(at: index)
        }
    }
}
class GameScene: SKScene, StackViewDelegate {
    var gameMenuView = GameMenuView()
    private var label : SKLabelNode?
    override func didMove(to view: SKView) {
        self.label = self.childNode(withName: "//helloLabel") as? SKLabelNode
        if let label = self.label {
            label.alpha = 0.0
            label.run(SKAction.fadeIn(withDuration: 2.0))
        }
        // Menu setup with stackView
        gameMenuView.frame=CGRect(x:20,y:50,width:280,height:200)
        view.addSubview(gameMenuView)
        gameMenuView.delegate = self
    }
    func didTapOnView(at index: Int) {
        switch index {
        case 0: print("tapped voice 1")
        case 1: print("tapped voice 2")
        case 2: print("tapped voice 3")
        case 3: print("tapped voice 4")
        case 4: print("tapped voice 5")
        default:break
        }
    }
}

Output : 输出

在此输入图像描述

在此输入图像描述

Approach: 做法:

The below mentioned code uses UIStackview to create 2 sections. 下面提到的代码使用UIStackview创建2个部分。 You could use a similar approach. 你可以使用类似的方法。

Output: 输出:

在此输入图像描述

Code: 码:

class ViewController: UIViewController {

    private let baseSection = UIStackView()
    private let section1    = UIStackView()

    private let titleLabel  = UILabel()
    private let button1     = UIButton(type: .custom)
    private let button2     = UIButton(type: .custom)
    private let button3     = UIButton(type: .custom)


    //MARK: Load view
    override func viewDidLoad() {
        super.viewDidLoad()

        setupViews()
    }


    //MARK: Setup views
    private func setupViews() {

        setupBaseSection()
        setupTitleLabel()
        setupButton1()
        setupSection1()
        setupButton2()
        setupButton3()
    }

    private func setupTitleLabel() {

        titleLabel.text      = "Swirl"
        titleLabel.font      = UIFont.preferredFont(forTextStyle: .headline)
        titleLabel.textColor = #colorLiteral(red: 0.8156862745, green: 0.9137254902, blue: 0.1647058824, alpha: 1)

        baseSection.addArrangedSubview(titleLabel)
    }

    private func setupButton1() {

        button1.backgroundColor = #colorLiteral(red: 0.9098039216, green: 0.168627451, blue: 0.3921568627, alpha: 1)

        baseSection.addArrangedSubview(button1)

        button1.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 0.2).isActive = true
        button1.heightAnchor.constraint(equalToConstant: 50).isActive = true
    }

    private func setupButton2() {

        button2.backgroundColor = #colorLiteral(red: 0.8156862745, green: 0.9137254902, blue: 0.1647058824, alpha: 1)

        section1.addArrangedSubview(button2)

        button2.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 0.1).isActive = true
        button2.heightAnchor.constraint(equalToConstant: 50).isActive = true
    }

    private func setupButton3() {

        button3.backgroundColor = #colorLiteral(red: 0.8156862745, green: 0.9137254902, blue: 0.1647058824, alpha: 1)

        section1.addArrangedSubview(button3)

        button3.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 0.2).isActive = true
        button3.heightAnchor.constraint(equalToConstant: 50).isActive = true
    }

    //MARKL Set up stack views

    private func setupBaseSection() {

        baseSection.axis          = .vertical
        baseSection.distribution  = .fill
        baseSection.alignment     = .center
        baseSection.spacing       = 10


        baseSection.translatesAutoresizingMaskIntoConstraints = false

        view.addSubview(baseSection)

        baseSection.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
        baseSection.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
        baseSection.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
    }

    private func setupSection1() {

        section1.axis         = .horizontal
        section1.distribution = .equalSpacing
        section1.alignment    = .fill
        section1.spacing      = 20

        baseSection.addArrangedSubview(section1)
    }
}

I experienced adding UIButtons and UILabels to a SpriteKit Scene can get very technical with the problem of positioning them. 我经历过将UIButtons和UILabels添加到SpriteKit场景中可以非常技术化地解决它们的问题。 Due to the fact that the UI Objects are positioned on the view and not on the SpriteKit Scene directly. 由于UI对象位于视图上而不是直接位于SpriteKit场景上。 You can use a SKSpriteNode as a Button and the SKLabelNode as a Title, For a menu scene. 您可以将SKSpriteNode用作Button,将SKLabelNode用作Title,用于菜单场景。

A Sprite kit scene is placed on the UIView and is scaled depending on the scale mode you define. Sprite工具包场景放置在UIView上,并根据您定义的缩放模式进行缩放。 Apples default scale mode .aspectFill requires no adjustment to Sprite kit objects positioning on different Phone device screen sizes. 苹果默认比例模式.aspectFill不需要调整定位在不同电话设备屏幕尺寸上的Sprite工具包对象。

This is a Custom Class of a SKSpriteNode with the same functionality as a button. 这是SKSpriteNode的自定义类,具有与按钮相同的功能。

 import Foundation
 import SpriteKit

 class ButtonLabelNode : SKSpriteNode {

let buttonPressed: () -> ()

init(texture: SKTexture?, color: UIColor, size: CGSize, text: String, buttonPressed: @escaping () -> ()) {

    self.buttonPressed = buttonPressed

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

    let label = SKLabelNode(fontNamed: "Futura")
    label.fontSize = 50
    label.fontColor = SKColor.red
    label.position = CGPoint.init(x: 0.0, y: 0.0)
    label.zPosition = 1
    label.verticalAlignmentMode = .center
    label.text = text
    self.addChild(label)

    self.isUserInteractionEnabled = true

}

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

    self.alpha = 0.8

}

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

    self.alpha = 1.0

  buttonPressed()
}

required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}

 }

When a touch begins on the SpriteNode the alpha decreases to 0.8 and back to 1.0 as the touch ends, Giving it the same visual affect of a UIButton. 当SpriteNode上的触摸开始时,alpha会降低到0.8,并在触摸结束时返回1.0,给予它与UIButton相同的视觉效果。 In the overridden function 'touchesEnded' there is a function that will be called every time the button is pressed, that function is added in the initializer and can be initialized in your game scene. 在重写的函数'touchesEnded'中,每次按下按钮时都会调用一个函数,该函数会在初始化程序中添加,并可在游戏场景中初始化。

override func didMove(to view: SKView) {

    let labelNode = LabelNode(texture: nil, color: .white, size: CGSize.init(width: 200, height: 100), text: "Play", buttonPressed: playButton)
    labelNode.position = CGPoint(x: self.frame.midX, y: self.frame.midY)

    self.addChild(labelNode)

    }

    func playButton() 
    {
    print("play")
     }

You can make as many instances of this class as you like, giving them their own functionality as the added initialised function is unique to its own instance. 您可以根据需要创建此类的多个实例,为其提供自己的功能,因为添加的初始化函数对于其自己的实例是唯一的。 Unlike having a required protocol method for the class as that will affect all instances of the class. 与类的必需协议方法不同,因为它会影响类的所有实例。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM