Scene(シーン)は、複数作っておいて移動するとアプリのクオリティが上がります。
例えば、ゲームでいえばタイトルシーンからゲームシーンへ、さらにゲームオーバーシーンに行って、またタイトルシーンに戻るといった流れです。

こんにちは!プログラミング高校生のロットです。
今回はシーンの移動について紹介します。
今回はSceneを3つ作って、各々で起きたイベントの数値をとある場所に任せて(Delegateして)タップした回数を計測するという単純なコードを作成します。
今回のポイントは3つです。
①シーンの移動
②タッチしたものを認識する
③数値をScene外に託して、それぞれの別のシーンでも利用する
タップしたものを感知する「touch begin」のコードは、必須スキルなのですぐに使えるようにしておきましょう。
シーン移動とタッチ回数の作成手順
①Sceneを3つ用意(SceneA、SceneB、SceneC)
②タップ回数をAppDelegateに託し、そこから各Sceneは数値を利用
③それぞれのScene内に次のSceneへ移動するコードを記入
目次
①Sceneを3つ用意(SceneA、SceneB、SceneC)
初期状態ではGameSceneは1つしかファイルがないので、あと2つ作成します。
左のプロジェクトファイルが並んでいるところで右クリック(ダブルタップ)をして、「New File...」をクリック。
「Swift File」を選んで「Next」をクリック。
ファイル名を入力して「Create」をクリック。
3つのGameSceneファイルのコードを以下に示します。
GameSceneA import SpriteKit import GameplayKit class GameSceneA: SKScene { //AppDelegateに託すための準備 let appDelegate:AppDelegate = UIApplication.shared.delegate as! AppDelegate //各種ラベルの準備 let countLabel = SKLabelNode(fontNamed: "Verdana-bold") let TitleLabel = SKLabelNode(fontNamed: "Verdana-bold") let NextLabel = SKLabelNode(fontNamed: "Verdana-bold") override func didMove(to view: SKView) { // 背景色をつける self.backgroundColor = UIColor.cyan // タイトルを表示する TitleLabel.text = "タイトル" TitleLabel.fontSize = 80 TitleLabel.horizontalAlignmentMode = .center TitleLabel.fontColor = SKColor.black TitleLabel.position = CGPoint(x:375, y:970) self.addChild(TitleLabel) // nextを表示する NextLabel.text = "始める" NextLabel.fontSize = 50 NextLabel.horizontalAlignmentMode = .center NextLabel.fontColor = SKColor.black NextLabel.position = CGPoint(x:375, y:570) self.addChild(NextLabel) // タップ回数を表示する countLabel.text = "タップは\(appDelegate.count)回" countLabel.fontSize = 50 countLabel.horizontalAlignmentMode = .center countLabel.fontColor = SKColor.black countLabel.position = CGPoint(x:375, y:70) self.addChild(countLabel) } func touchDown(atPoint pos : CGPoint) { } func touchMoved(toPoint pos : CGPoint) { } func touchUp(atPoint pos : CGPoint) { } override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { for touch: AnyObject in touches { // タッチされた位置にあるものを調べて let location = touch.location(in: self) let touchNode = self.atPoint(location) // もしタッチされたものがNextLabelだったら・・ if touchNode == NextLabel { //AppDegateのスコアを加算 appDelegate.count += 1 //Sceneを切り換える let scene = GameSceneB(size: self.size) let skView = self.view! scene.scaleMode = SKSceneScaleMode.aspectFit skView.presentScene(scene) } } } override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) { } override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) { } override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) { } override func update(_ currentTime: TimeInterval) { } }
GameSceneB import SpriteKit import GameplayKit class GameSceneB: SKScene { //AppDelegateに託すための準備 let appDelegate:AppDelegate = UIApplication.shared.delegate as! AppDelegate //各種ラベルの準備 let countLabel = SKLabelNode(fontNamed: "Verdana-bold") let GameLabel = SKLabelNode(fontNamed: "Verdana-bold") let NextLabel = SKLabelNode(fontNamed: "Verdana-bold") override func didMove(to view: SKView) { // 背景色をつける self.backgroundColor = UIColor.green // ゲームシーンを表示する GameLabel.text = "ゲームシーン" GameLabel.fontSize = 80 GameLabel.horizontalAlignmentMode = .center GameLabel.fontColor = SKColor.black GameLabel.position = CGPoint(x:375, y:970) self.addChild(GameLabel) // nextを表示する NextLabel.text = "結果へ" NextLabel.fontSize = 50 NextLabel.horizontalAlignmentMode = .center NextLabel.fontColor = SKColor.black NextLabel.position = CGPoint(x:375, y:570) self.addChild(NextLabel) // タップ回数を表示する countLabel.text = "タップは\(appDelegate.count)回" countLabel.fontSize = 50 countLabel.horizontalAlignmentMode = .center countLabel.fontColor = SKColor.black countLabel.position = CGPoint(x:375, y:70) self.addChild(countLabel) } func touchDown(atPoint pos : CGPoint) { } func touchMoved(toPoint pos : CGPoint) { } func touchUp(atPoint pos : CGPoint) { } override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { for touch: AnyObject in touches { // タッチされた位置にあるものを調べて let location = touch.location(in: self) let touchNode = self.atPoint(location) // もしタッチされたものがNextLabelだったら・・ if touchNode == NextLabel { //AppDegateのスコアを加算 appDelegate.count += 1 //Sceneを切り換える let scene = GameSceneC(size: self.size) let skView = self.view! scene.scaleMode = SKSceneScaleMode.aspectFit skView.presentScene(scene) } } } override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) { } override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) { } override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) { } override func update(_ currentTime: TimeInterval) { } }
GameSceneC import SpriteKit import GameplayKit class GameSceneC: SKScene { //AppDelegateに託すための準備 let appDelegate:AppDelegate = UIApplication.shared.delegate as! AppDelegate //各種ラベルの準備 let countLabel = SKLabelNode(fontNamed: "Verdana-bold") let GameOverLabel = SKLabelNode(fontNamed: "Verdana-bold") let NextLabel = SKLabelNode(fontNamed: "Verdana-bold") override func didMove(to view: SKView) { // 背景色をつける self.backgroundColor = UIColor.lightGray // ゲームオーバーを表示する GameOverLabel.text = "ゲームオーバー" GameOverLabel.fontSize = 80 GameOverLabel.horizontalAlignmentMode = .center GameOverLabel.fontColor = SKColor.black GameOverLabel.position = CGPoint(x:375, y:970) self.addChild(GameOverLabel) // nextを表示する NextLabel.text = "タイトルへ戻る" NextLabel.fontSize = 50 NextLabel.horizontalAlignmentMode = .center NextLabel.fontColor = SKColor.black NextLabel.position = CGPoint(x:375, y:570) self.addChild(NextLabel) // タップ回数を表示する countLabel.text = "タップは\(appDelegate.count)回" countLabel.fontSize = 50 countLabel.horizontalAlignmentMode = .center countLabel.fontColor = SKColor.black countLabel.position = CGPoint(x:375, y:70) self.addChild(countLabel) } func touchDown(atPoint pos : CGPoint) { } func touchMoved(toPoint pos : CGPoint) { } func touchUp(atPoint pos : CGPoint) { } override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { for touch: AnyObject in touches { // タッチされた位置にあるものを調べて let location = touch.location(in: self) let touchNode = self.atPoint(location) // もしタッチされたものがNextLabelだったら・・ if touchNode == NextLabel { //AppDegateのスコアを加算 appDelegate.count += 1 //Sceneを切り換える let scene = GameSceneA(size: self.size) let skView = self.view! scene.scaleMode = SKSceneScaleMode.aspectFit skView.presentScene(scene) } } } override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) { } override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) { } override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) { } override func update(_ currentTime: TimeInterval) { } }
上記、一応3つとも載せておきました。
②タップ回数をAppDelegateに託し、そこから各Sceneは数値を利用
既に各GameSceneに下記コードを書いています。
//AppDelegateに託すための準備
let appDelegate:AppDelegate = UIApplication.shared.delegate as! AppDelegate
これによって、「Appdelegate.swift」で定義したものを読み取ることができます。
Appdelegate.swiftファイルに、タップ回数を変数で用意します。
以下にコードを示します。
AppDelegate.swift import UIKit @main class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? //カウントを変数で用意 var count = 0 func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { return true } func applicationWillResignActive(_ application: UIApplication) { } func applicationDidEnterBackground(_ application: UIApplication) { } func applicationWillEnterForeground(_ application: UIApplication) { } func applicationDidBecomeActive(_ application: UIApplication) { } }
countという変数を増やしただけです。
これを各クラスで共有します。
③それぞれのScene内に次のSceneへ移動するコードを記入
既に各GameSceneに下記コードを書いています。
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch: AnyObject in touches {
// タッチされた位置にあるものを調べて
let location = touch.location(in: self)
let touchNode = self.atPoint(location)
// もしタッチされたものがNextLabelだったら・・
if touchNode == NextLabel {
//AppDegateのスコアを加算
appDelegate.count += 1
//Sceneを切り換える
let scene = GameSceneB(size: self.size)
let skView = self.view!
scene.scaleMode = SKSceneScaleMode.aspectFit
skView.presentScene(scene)
}
}
}
この部分で、タッチしたものを感知し、それをタッチしたら次のシーンへいくようにしています。
よく見るとなんとなく理解できるかと思います。
今は深く追求しなくていいと思います。
今回は以上です。