XcodeのGameテンプレートから不要なファイルとコードを削除して、汎用的なSpriteKitテンプレートにする方法についてまとめる
0. 前提条件
この記事を執筆したときの前提条件は以下の通り。
- Xcode : 10.3
- macOS : 10.14.6 (Mojave)
- 言語 : Swift
1. Xcode新規プロジェクトの作成
Xcodeのメニューから「File」->「new」->「Project」
「Game」テンプレートを選択
「Choose options for your new project:」ダイアログにて以下を指定
- Game Technology : SpriteKit
- Language : Swift
- 他 : 任意
2. GameScense.sksを削除
Xcodeナビゲータにて「GameScense.sks」を選択して「Delete」
確認ダイアログにて「Move to Trush」を選択
3. GameViewController.swiftの内容を書き換える
「GameViewController.swift」を以下の内容に書き換える
GameViewController.swift
import UIKit
import SpriteKit
class GameViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let scene = GameScene() //GameScenseクラスをインスタンス化
if let skView = self.view as! SKView? {
skView.showsFPS = true
skView.showsNodeCount = true
skView.showsDrawCount = true
//skView.ignoresSiblingOrder = true
scene.scaleMode = .aspectFill
scene.size = skView.frame.size //skViewのサイズを設定
skView.presentScene(scene)
}
}
override var shouldAutorotate: Bool {
return true
}
override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
if UIDevice.current.userInterfaceIdiom == .phone {
return .allButUpsideDown
} else {
return .all
}
}
override var prefersStatusBarHidden: Bool {
return true
}
}
4. GameScene.swiftの内容を書き換える
「GameScene.swift」を以下の内容に書き換える
GameScene.swift
import SpriteKit
class GameScene: SKScene {
enum ColliderType {
static let xxx1: UInt32 = 1 << 0
static let xxx2: UInt32 = 1 << 1
static let xxx3: UInt32 = 1 << 2
static let xxx4: UInt32 = 1 << 3
static let xxx5: UInt32 = 1 << 4
}
override func didMove(to view: SKView) {
self.physicsWorld.gravity = CGVector(dx: 0.0, dy: -2.0)
self.physicsWorld.contactDelegate = self
//TODO
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches {
let location = touch.location(in: self)
let touchedNode = atPoint(touch.location(in: self))
switch touchedNode.name {
case "xxx":
//TODO
break
default:
break
}
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
//TODO
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
//TODO
}
override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
//TODO
}
override func update(_ currentTime: TimeInterval) {
//TODO
}
}
extension GameScene: SKPhysicsContactDelegate {
func didBegin(_ contact: SKPhysicsContact) {
//TODO
}
}
以上
おまけ
SpriteKitを使う上であると便利なエクステンションを書いておく
おまけ
extension Int {
var withComma: String {
let formatter = NumberFormatter()
formatter.numberStyle = .decimal
let commaString = formatter.string(from: self as NSNumber)
return commaString ?? "\(self)"
}
var toFloat: CGFloat {
return CGFloat(self)
}
var toDouble: Double {
return Double(self)
}
}
extension CGFloat {
var toInt: Int {
return Int(self)
}
var toDouble: Double {
return Double(self)
}
}
extension Double {
var toFloat: CGFloat {
return CGFloat(self)
}
}
import AudioToolbox
func tick(_ id: SystemSoundID = 1003) {
AudioServicesPlaySystemSound(id)
AudioServicesDisposeSystemSoundID(id)
}
おまけ2 (2019.10.5追記)
SpriteKitでノードを構築していく場合に、インスタンス生成後に各プロパティを設定するコードがだらだら続くが、これをいい感じに書く方法を見つけたので、追記しておきます。
これまでの書き方
let label = SKLabelNode(fontNamed: "HelveticaNeue")
label.horizontalAlignmentMode = .center
label.verticalAlignmentMode = .center
label.text = "LABEL"
label.fontSize = 32
label.fontColor = .white
label.position = CGPoint(x: view.frame.midX, y: view.frame.midY)
addChild(label)
まとまりのある書き方
let label: SKLabelNode = {
$0.horizontalAlignmentMode = .center
$0.verticalAlignmentMode = .center
$0.text = "LABEL"
$0.fontSize = 32
$0.position = CGPoint(x: view.frame.midX, y: view.frame.midY)
return $0
} (SKLabelNode(fontNamed: "HelveticaNeue"))
addChild(label)