2017-03-13 14 views
1

私は速くて新しく、ゲームを作成したSKSceneを持っています。私はしかし、メニューを構築する方法を把握するように見えることはできません。両方のソリューションが別のView Controllerまたは別のSKSceneを作成するのを見た場合、それらはすべて非常に混乱し複雑です。私はこれらの方法や他の方法のいずれかを使用するために開いています、誰もこの問題に取り組むための任意のトリックを持っています。いくつかのコードが役に立ちます。助けてくれてありがとう。spritekit swiftを使用して迅速にゲーム用のメインメニューを作成する

+0

あなたが達成したいと思っているUIの図を描くことができますか?それはちょうどボックスとのブロックダイアグラムかもしれません。 – user1046037

+2

これを達成するために 'UIStackview'を使うことができます。私はコンピュータに着くとコードを投稿して投稿します。その間に 'UIStackview'について読むことができます。 – user1046037

+0

@ user1046037 SKSceneにスタックビューを挿入するには – joshLor

答えて

2

スプライト・キットでメニューを得るために多くの方法があります。

通常、メニューボイスを作成するには、SKLabelNodeまたはSKSpriteNodeを描画するか、この種の構造を構築する特定のSKNodeを作成します。

しかし、私はStackViewについてのコメントの提案に従いたいと思います。

は、列または行のいずれかのビュー のコレクションをレイアウトするための合理化されたインターフェイスを提供し:我々は知っているStackView はことUIKit要素です。

そこで、我々は、すべてのメニューの声が含まれている垂直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

メニューを隠すのは適切ではありません。単にアルファや 'isHidden'プロパティ、' zPosition'プロパティを変更することはできますが、それは間違った方法ではありません。 –

+0

私はアニメーションのためだけにスライドインしましたしかし、私が心配していたことは、それが自分の試合を遅らせるということです。 – joshLor

1

アプローチ:

下記のコードは、2つのセクションを作成するUIStackviewを使用します。 同様のアプローチを使用できます。

出力:

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

私はSpriteKitシーンにUIButtonsとUILabelsを追加した経験があり、それらを配置する問題で非常に技術的になる可能性があります。 UIオブジェクトはビュー上に配置され、SpriteKitシーンには直接配置されないためです。 SKSpriteNodeをボタンとして使用し、SKLabelNodeをタイトルとして使用することができます(メニューシーンの場合)。

スプライトキットのシーンは、UIViewに配置され、定義したスケールモードに応じてスケーリングされます。 Applesデフォルトの縮尺モード.aspectFillでは、異なる電話機の画面サイズに配置された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でタッチが開始されると、アルファは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") 
    } 

あなたが好きなように、このクラスのように多くのインスタンスを作る追加初期化機能は、独自のインスタンスに固有のものであるとして、それらに彼ら自身の機能性を与えることができます。クラスのために必要なプロトコルメソッドを持つのと違って、クラスのすべてのインスタンスに影響します。

関連する問題