【備忘録】SpriteKitのテンプレート

## 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」を以下の内容に書き換える

```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」を以下の内容に書き換える

```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を使う上であると便利なエクステンションを書いておく

```Swift:おまけ
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でノードを構築していく場合に、インスタンス生成後に各プロパティを設定するコードがだらだら続くが、これをいい感じに書く方法を見つけたので、追記しておきます。

```Swift:これまでの書き方
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)
```

```Swift:まとまりのある書き方
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)
```