【GameplayKit】ゲームを効率的につくるためのフレームワーク①

#この記事について
iOSアプリでゲームを作成するには、Unityが主流のようですがAppleもいろいろ頑張っているようでXcodeにも`GameplayKit`なるフレームワークが追加され強化されているようです。
どのようなものか、どうやって使うのか知りたいのですが、小生のような凡人が理解できるレベルの情報があまりないようなので調査しました。
内容はほとんど、Appleのデベロッパサイト及びサンプルコードを適当に翻訳・解説したものになります。誤った部分などお気付きの点は、遠慮なくご指摘お願いします。
なお、`SceneKit`の基本的な使い方は[こちらの記事](http://qiita.com/chino_tweet/items/97c4b39f0ea0ca53fb43)・Xcodeの基本的な使い方はこちら（[iBooksで見る](https://geo.itunes.apple.com/jp/book/hello-world.-swift3/id1172722589?mt=11)）をどうぞ。

#GameplayKit
まず、実装できる機能について7つの目的が挙げられています。
1. Randomization
2. Entities and Components
3. State Machines
4. The Minmax Strategist
5. Pathfinding
6. Agent, Goals, and Behaviors
7. Rule Systems

#解説するサンプルコード
Appleデベロッパサイトに[Boxes: GameplayKit Entity- Component Basics](https://developer.apple.com/library/content/samplecode/Boxes_GamePlayKit/Introduction/Intro.html#//apple_ref/doc/uid/TP40016459)なるサンプルプロジェクトがあったので、調べました。プロジェクトにはmacやappleTV向けのコードもありましたが、ここではiOSに限って調べました。
このサンプルは、Entities and Componentsの理解を目的としているようです。

<img width="680" alt="Boxes_2x.png" src="https://qiita-image-store.s3.amazonaws.com/0/70476/5d38b11c-9f03-e486-ee50-4403728666f3.png">
サンプルは「画面をタップするとブロックが跳ねる」ゲームです。ご覧の通り、`SceneKit`の3D機能も使っているようですが、果たしてここに`GameplayKit`がどこでどんなふうに実装されているのかを追って調べていきたいと思います。

##主なクラス
このサンプルプロジェクトでは、`GameplayKit`フレームワークにある以下のクラスを扱っています。

###GKEntityクラス
  ゲーム画面にある5色のボックスは、`GKEntity`オブジェクト。
###GKComponentクラス
このクラスのインスタンス（コンポーネント）が、ボックスに与えるべき機能をまとめる。
まとめられる機能によって、インスタンスがいくつか定義してある。それぞれのボックスが実装するコンポーネントを組み合わされることで、ボックスが特徴づけられる。

- GeometryComponent（全てのボックスが実装）
- ParticleComponent（黄色と青のボックスが実装）
- PlayerControlComponent（緑と青のボックスが実装）  

###GKComponentSystemクラス

##サンプルプロジェクトの解説
###Game.swift
シーンのクラスファイル。`setUpEntities()`メソッドで、エンティティに各種コンポーネントを実装している。
###GeometryComponent.swift
全てのボックスが実装するコンポーネント。`SceneKit`のオブジェクトに物理的な挙動などを設定する。
###ParticleComponent.swift
このコンポーネントを実装したボックスは、炎とスパークのパーティクル（粒子の演出）を表示する。
###PlayerControlComponent.swift
このコンポーネントを実装したボックスは、プレイヤーがアプリに対してインタラクション（iOSなら画面タップ）するたびに跳ね上がる。

#再現手順
大まかな流れは以下の通りです。
1. プロジェクト作成
2. シーンファイル作成
3. フロアオブジェクトを配置
4. ブロックオブジェクトを配置
5. 照明オブジェクトを配置
6. カメラオブジェクトを配置
7. `Game`クラスを定義

##プロジェクト作成
シングルビューテンプレートを選択する。
ファイル名を変更（ViewController.swift => GameViewController.swift）する。
ビューコントローラのIdentity Inspectorの設定を変更する。

- クラスファイルをGameViewControllerクラスに変更
- ルートビューを`SCNView`クラスに変更

##シーンファイル作成
SceneKit Scene Fileを新規作成（GameScene.scn）

##フロアオブジェクトを配置
オブジェクトライブラリから、Floorを配置する。
インスペクタエリアの設定を以下のように変更する。

- Physics Type: Static
- Diffuse: Black
- ambient: Black

##ブロックオブジェクトを配置
シーンファイルを表示する。
オブジェクトライブラリから、Boxを5つ（redBox, yellowBox, greenBox, blueBox, purpleBox）配置しする。
Material Inspectorから色（Diffuse）を変更する。
Physics Inspectorで、PhysicsTypeをDynamicに変更する。
全てのブロックSizeは、Width, Height, Length を1に設定
Position(x, y, z)は以下のとおり。

- redBox    (x:-4, y: 0.5, z:0)
- yellowBox (x:-2, y: 0.5, z:0)
- greenBox  (x: 0, y: 0.5, z:0)
- blueBox   (x: 2, y: 0.5, z:0)
- purpleBox (x: 4, y: 0.5, z:0)

##照明オブジェクトを配置
オブジェクトライブラリから、Ambient lightとDiractional lightを一つずつ配置する。
Node Inspectorからそれぞれのライトのオイラー角と位置を設定する。

- ambient
 - Position(x:0, y:12, z:0)
 - Euler   (x:0, y:0, z:0)
- directional
 - Position(x:10, y:10, z:10)
 - Euler   (x:-45, y:0, z:45)

##カメラオブジェクトを配置
オブジェクトライブラリから、Cameraを配置する。
Node Inspectorから位置とオイラー角を設定する。

- Position(x:0, y:3, z:10)
- Euler   (x:0, y:0, z:0)

Attribute Inspectorから画角Projection(Xfov:0°, Yfov:45°)を設定する。

##Gameクラスを定義
Cocoa Touch Classテンプレートから`NSObject`のサブクラスを新規作成する。（Game.swift）
`Game`クラスを定義する。

```ruby:Game.swift
import SceneKit

class Game: NSObject, SCNSceneRendererDelegate {
    let scene = SCNScene(named: "GameScene.scn")!
}
```

##ビューコントローラにシーンを表示


```ruby:GameViewController.swift
import UIKit
import SceneKit

class GameViewController: UIViewController {
    let game = Game()

    override func viewDidLoad() {
        super.viewDidLoad()
        
        guard let scnView = view as? SCNView else { fatalError("Unexpected view class") }
        
        scnView.backgroundColor = UIColor.lightGray
        scnView.scene = game.scene        
    }
}

```

##ビルド
いったん、シーンが正しく表示されるかを確認しておきましょう。

#続く
長くなってきたので、続きは別記事にすることにします。
[ゲームを効率的につくるためのフレームワーク②](http://qiita.com/chino_tweet/items/bb1b28e3910d275bd479)
各種コンポーネントを定義して、任意のエンティティに実装していきます。