2017-03-13 66 views
1

我是新来的swift,并且有一个SKScene,我在其中创建了一个游戏。我似乎无法弄清楚,但是如何构建菜单。如果看到两种解决方案创建另一个视图控制器或另一个SKScene,但它们都非常混乱和复杂。我愿意使用这些方法或任何其他方法,是否有人有任何技巧来解决这个问题。一些代码会有帮助。谢谢您的帮助。使用spritekit swift创建游戏的主菜单

+0

可以请您画一张您希望实现的用户界面图。它可能只是框中的框图。 – user1046037

+2

你可以使用'UIStackview'来实现这一点。当我到达计算机时,会尝试并发布代码。在此期间您可以阅读有关“UIStackview”的内容。 – user1046037

+0

@ user1046037我该如何在SKScene中放置一个堆栈视图 – joshLor

回答

2

有很多种方法获得雪碧套件的菜单。

通常人们会画一些SKLabelNodeSKSpriteNode来建立菜单声音或制作一个构建这种结构的特定SKNode

但是我想对关于StackView的评论提出建议。 我们知道StackViewUIKit元素:

提供了铺设的意见 在任一列或行集合的简化的界面。

因此,我们可以建立一个垂直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 
     } 
    } 
} 

输出

enter image description here

enter image description here

+0

在我问这个问题并得到答案之间的时间内,我做了一个简单的解决我的问题。我创建了一个与我的场景一样大小的SKSprite节点,并将它移出“屏幕显示框”。然后,每当我想打电话时,我都会将它移到“屏幕显示框”中。我应该知道这个解决方案有什么问题吗? – joshLor

+0

这不是一个很好的隐藏你的菜单的方法,你可以简单地改变alpha或'isHidden'属性,'zPosition'属性,但它不是一个错误的方法。 –

+0

我只是让它滑动动画,但我担心的是它会减慢我的比赛速度。 – joshLor

1

方法:

下面提到的代码使用UIStackview创建2个部分。 你可以使用类似的方法。

输出:

enter image description here

代码:

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) 
    } 
} 
+2

谢谢,但我需要代码才能使它在SKScene中工作 – joshLor

+0

为什么它必须是SSKcene?难道它不是一个单独的视图控制器作为场景上的叠加层吗?视图控制器不需要覆盖整个屏幕,甚至可以是屏幕的一部分。 – user1046037

+1

这是真的,但我需要知道如何从视图控制器更改为SKScene – joshLor

0

我经历过将UIButtons和UILabels添加到SpriteKit场景可以获得非常技术性的定位问题。由于UI对象位于视图上,而不是直接位于SpriteKit场景中。您可以将SKSpriteNode用作按钮,将SKLabelNode用作标题,用于菜单场景。

Sprite工具包场景放置在UIView上,并根据您定义的缩放模式进行缩放。苹果默认缩放模式.aspectFill不需要调整位于不同Phone设备屏幕尺寸上的Sprite套件对象。

这是一个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") 
} 

} 

当SpriteNode上的触摸开始时,alpha减少到0.8并回到1。0作为触摸结束,赋予其与UIButton相同的视觉效果。在被覆盖的函数'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") 
    } 

只要你喜欢你可以让这个类的多个实例,让他们自己的功能添加的初始化函数是独一无二的自己的实例。与为类提供所需的协议方法不同,因为这会影响类的所有实例。