Edited at

SpriteKitでベースクラスをつくってシーン管理する(Swift)

More than 3 years have passed since last update.

初めてSwiftのSpriteKitでアプリをつくって、シーン管理どうしようか最初に色々考えてみたのでメモ。

結論でいうと、SKSceneを継承したBaseSceneなるものをつくり、すべてのシーンはBaseSceneを継承することにする。

BaseScene内にシーンの移動処理を書く。


いいなと思った点


  • 実際にいろいろ処理を書くシーンに、シーン切り替え周りでいろいろ書く必要がない

  • シーンの切り替えというよりはベースシーンがあることで、ベースシーンにもSKNodeを置いて、どのシーンでも共通して必要なものがまとめて書けた(ヘッダー要素とか)

  • BaseSceneでデリゲートなりリスナーを用意することで現在のシーンクラスじゃないところからシーン切り替えができた。

  • 最後までアプリつくることができた。


微妙だと思った点


  • 事前に色々調べたがこんなことしてる人いなさそうだった

  • SwiftもSpriteKitも初めてなのでベストな方法がよくわかっていないので不安

  • シーン数多くなってきたら行数が膨らむのでそれ対策を考えたい


ファイル構成

--

GameのSpriteKitではなく

Single Veiw Applicationで作成

元からあるものなどは省略

/ViewController.swift

/SceneView.swift

/Scenes/BaseScene.swift

/Scenes/Scene1.swift

/Scenes/Scene2.swift

/Scenes/Scene3.swift

/Scenes/Scene4.swift


実装例

実際に書いたものから不必要な部分を削っただけなので

どこか足りなくて動かなかったらすみません。


ViewController.swift

import UIKit

import SpriteKit

class ViewController: UIViewController{

private var sceneView: SceneView?

override func viewDidLoad() {
super.viewDidLoad()

sceneView = SceneView(frame: self.view.frame)
self.view = sceneView
}
}



SceneView.swift

 import Foundation

import SpriteKit
import EmitterKit

class SceneView: SKView{

override init(frame: CGRect) {
super.init(frame: frame)
self.showsFPS = true
self.showsNodeCount = true
self.ignoresSiblingOrder = true
self.frameInterval = 1

//最初のシーン
let scene:SKScene!

scene = Scene1(size: self.bounds.size)

scene.scaleMode = SKSceneScaleMode.AspectFill
self.presentScene(scene)
}

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

}



BaseScene.swift

 import Foundation

import SpriteKit

class BaseScene: SKScene {

override func didMoveToView(view: SKView) {
//共通nodeとか置ける
}

override func update(currentTime: NSTimeInterval) {
//どのシーンでも共通してループするものがあれば
}

//シーンを切り替える関数
func changeToScene1(){
let scene = Scene1(size: self.scene!.size)
scene.scaleMode = SKSceneScaleMode.AspectFill
self.scene!.view?.presentScene(scene)
}

func changeToScene2(){
let scene = Scene2(size: self.scene!.size)
scene.scaleMode = SKSceneScaleMode.AspectFill
self.scene!.view?.presentScene(scene)
}

func changeToScene3(){
let scene = Scene3(size: self.scene!.size)
scene.scaleMode = SKSceneScaleMode.AspectFill
self.scene!.view?.presentScene(scene)
}

func changeToScene4(){
let scene = Scene4(size: self.scene!.size)
scene.scaleMode = SKSceneScaleMode.AspectFill
self.scene!.view?.presentScene(scene)
}

}



Scene1.Swift

import SpriteKit

class Scene1: BaseScene {
override func didMoveToView(view: SKView) {
super.didMoveToView(view)

}

override func update(currentTime: NSTimeInterval) {
super.update(currentTime)

}

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
super.changeToScene2()
}

deinit{
print("deinit Scene1")
}
}


Scene2~4はScene1とほとんど同じ

--