プログラミング

【Swift】複数のSceneを移動する(タッチと数値共有)

Scene(シーン)は、複数作っておいて移動するとアプリのクオリティが上がります。

例えば、ゲームでいえばタイトルシーンからゲームシーンへ、さらにゲームオーバーシーンに行って、またタイトルシーンに戻るといった流れです。

 

こんにちは!プログラミング高校生のロットです。

今回はシーンの移動について紹介します。

 

今回はSceneを3つ作って、各々で起きたイベントの数値をとある場所に任せて(Delegateして)タップした回数を計測するという単純なコードを作成します。

 

今回のポイントは3つです。

①シーンの移動

②タッチしたものを認識する

③数値をScene外に託して、それぞれの別のシーンでも利用する

 

タップしたものを感知する「touch begin」のコードは、必須スキルなのですぐに使えるようにしておきましょう。

 

 

シーン移動とタッチ回数の作成手順

Scene3つ用意(SceneASceneBSceneC

②タップ回数を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)

            }

        }

    }

 

この部分で、タッチしたものを感知し、それをタッチしたら次のシーンへいくようにしています。

 

よく見るとなんとなく理解できるかと思います。

今は深く追求しなくていいと思います。

 

今回は以上です。

 

 

-プログラミング
-

© 2021 『自由の翼』ブロガーLIFE