初心者のためのSprite Kit入門

# はじめに
こんにちは。
つい先日、Apple純正のゲーム開発フレームワークである「SpriteKit」を使ったゲームアプリをリリースしました。
「Bumping Ball+」というタップ操作のみで簡単に遊べる、シューティングゲームです。
SpriteKitの動きや操作感などが気になる方は気楽に遊んでみてください。
[<img src="http://bumpingball.net/images/logo.png" width="180" alt="Bumping Ball+">](https://itunes.apple.com/us/app/bumping-ball+/id1148383719?l=ja&ls=1&mt=8)
**[ダウンロードはこちら](https://itunes.apple.com/us/app/bumping-ball+/id1148383719?l=ja&ls=1&mt=8)**

# 背景
私はSwiftで書きたかったということと物理演算を使いたかったという２つの理由で、Spritekitを採用しました。ゲームアプリであればcocos2d-xやUnityなどが有名ではありますが、簡易的に物理演算を使いたかったということと学習コストの低さを優先して、今回これらは採用しませんでした。
より本格的なゲームを作りたい方やC++が得意な方はSpritekitをわざわざ採用する理由は少ないかもしれません。unityなどはAndroidでもビルドできますし。最近では[海外の9割弱はAndoridユーザである](http://japan.cnet.com/marketers/news/35091602/)という調査も出ていて、海外ユーザを視野に入れいているゲームであるならば、なおさらAndoroidに対応する必要があるといえますね。

# 概要
Spritekitでは主にview・scene・node・actionという４つの要素が存在し、これらの役割さえ理解できてしまえば、あとはリファレンス見ながらコツコツ開発をすすめることができると思います。以下に当アプリのプレイ画面を例に要素を並べてみました。

| 要素| 役割 | クラス |
|:-:|:-:|:-:|
| view  | UIViewのサブクラスです。描画を担当します。  | SKView  |
| scene  | ゲームの画面です。この上にノードやビューを重ねていきます。  | SKScene  |
| node  | テキストやキャラクター、画像などの物体を表示します。  | SKNode, SKSpriteNode, SKLabelNode...  |
| action  | 爆発や移動などnodeをアニメーションさせます。  | SKAction |

<img src="https://qiita-image-store.s3.amazonaws.com/0/116692/572a11e7-726e-ed4a-f798-f8672f5138f3.png" width="414">

上記の例のようにSKViewにSKScene、SKSceneにSKNodeを重ねて描画を制裁しています。SKActionでフェードアウトアニメーションや爆発などを表現できます。ステージ制ゲームの場合、一つのSKViewにステージごとに複数枚用意したSKSceneを重ねかえていく処理になると思います。

# シーンの土台を作成してみる
では、実際にシーンを表示するために必要なコンポーネントを作成します。
まずSKViewのViewControllerを通常通り作成し、```SceneViewController.swift```とします。
次にsksファイルを作成します。  
File > New > File からSpriteKit Sceneを選択し、```MyScene.sks```を作成します。
<img src="https://qiita-image-store.s3.amazonaws.com/0/116692/1dc29ba3-cc86-dcbf-2bec-8ed438eda829.png" width="717">



これで準備が整ったので、SceneViewControllerのUIViewをSKViewとして定義し、SKSceneを重ねます。

```swift:SceneViewController.swift
import SpriteKit

class SceneViewController: UIViewController {
  let skView = SKView()  

  override func viewDidLoad() {
      super.viewDidLoad()
      
      if let scene = MyScene(fileNamed:"MyScene") {
            let screensize = UIScreen.main.bounds.size
            skView.frame = CGRect(x: 0, y: 0, width: screensize.width, height: screensize.height)
            skView.showsFPS = true //sceneのfpsを表示します（開発用）
            skView.showsNodeCount = true //sceneに表示されているノード数を表示します（開発用）
            
            /* Sprite Kit applies additional optimizations to improve rendering performance */
            skView.ignoresSiblingOrder = true
            
            /* Set the scale mode to scale to fit the window */
            scene.scaleMode = .resizeFill
            
            skView.allowsTransparency = true
            skView.presentScene(scene)  //sceneをskviewに重ねます
            self.view.addSubview(skView) //skviewをuiviewに重ねます
      }
  }
}
```
とりあえずこれで```SKViewController > SKView > SKScene```という構図ができあがりました。

# シーンを作成してみる
では、実際にシーンを作成していきます。
File > New > FileからCocoa Touch Classを選択してください。subclassをSKSceneに設定します。
<img width="717" alt="スクリーンショット 0029-01-03 16.35.11.png" src="https://qiita-image-store.s3.amazonaws.com/0/116692/2863b8d0-03c0-704f-f0d7-22ce25dc40c7.png">

必要に応じてメソッドをオーバーライドしてください。

```swift:MyScene.swift
import SpriteKit
import UIKit

class MyScene: SKScene, SKPhysicsContactDelegate {

  override func didMove(to view: SKView) {
    //シーンが生成されたタイミングで呼ばれます
  }

  override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    //sceneにタッチした処理
  }
  override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
    //タッチして動かした処理
  }

  //このメソッドが毎回呼ばれます
  override func update(_ currentTime: TimeInterval) {
    super.update(currentTime)
  }

  //衝突判定処理
  func didBegin(_ contact: SKPhysicsContact) {
  }
}
```

まず継承している```SKPhysicsContactDelegate```クラスですがこちらを継承することで物理演算処理が可能になります。 他にもtouchBeganやtouchEndなどシーンのタッチ処理をかんたんに取得できます。update処理はシーンが動き出してから毎回呼ばれます。試しにprint出力してみると動きがわかりやすいと思います。updateを止めたい場合はskviewに```isPaused```というプロパティが用意されており、こちらを```false```にすることでシーン上のすべての処理が停止します。（一時停止処理などが使用用途でしょうか）

とりあえずこの状態でビルドしてみます。
まっさらではありますが、右下にノードとfpsが表示されていれば問題ないです。
<img width="414" alt="Simulator Screen Shot H29.01.03 17.12.50.png" src="https://qiita-image-store.s3.amazonaws.com/0/116692/4ca08f20-1821-7dfa-6076-49d1ecc440db.png">

# ノードを重ねてみる
適当にラベルと画像を表示させてみます。
ラベルは```SKLabelNode```、画像は```SKSpriteNode```をそれぞれ使用します。
背景もbackgroudColorで変更できます。また座標位置に関して、sksceneとUIViewで異なりますので注意してください。

```swift:MyScene.swift
    override func didMove(to view: SKView) {
        //シーンが生成されたタイミングで呼ばれます
        
//        背景を変更します
        self.backgroundColor = SKColor.black
        
//        イメージ
        let node = SKSpriteNode(imageNamed:"sample")
        addChild(node)
        
        //        ラベル
        let label = SKLabelNode(fontNamed: "Chalkduster")
        label.text = "Hello, World!!"
        let labelSize: CGFloat = 50.0
        label.fontSize = labelSize
        label.position = CGPoint(x:self.frame.midX, y:self.frame.height/2 - labelSize)
        label.fontColor = SKColor.yellow
        self.addChild(label)
    }
```
こんな感じにサクッと表示できちゃいます。
<img width="414" src="https://qiita-image-store.s3.amazonaws.com/0/116692/8d25ba59-3340-2622-a40e-9b31120caeea.png">

今回は、SpriteKitの入門として要素の役割の紹介や、簡単なシーンの作成までを紹介しました。他要素のアクションや当たり判定などもこんな感じでサクッとできちゃいますので、色々試してみると楽しいかもしません。何か間違っている箇所などありましたらご指摘くださいませ。

# 参考
* [Sprite Kitでブロック崩し](http://qiita.com/tnantoka/items/5c24e72dc569da1c9b62)
* [Sprite Kit入門](http://spritekit.senchan-office.com/)