Cocos2d v3 SpriteBuilderとSwiftのコンポーネント接続、様々なアニメーションについて

# 前回まで
* [SpriteBuilderの導入](http://qiita.com/syou007/items/9e6202a88495757dda5f)
* [SpriteBuilderでできたものの確認](http://qiita.com/syou007/items/1cd8b0d2deeb5acd38f1)
* [CocoaPodsのインストール](http://qiita.com/syou007/items/957dd2d9c3ff1b2a7c6d)
* [SpriteBuilderとXCodeで画面遷移する](http://qiita.com/syou007/items/9bebb01aff70dec0e3f3)

# 今回のゴール
今回は少し横道に逸れます。
SpriteBuilderで配置したコンポーネントの扱いについて記載します。

今回の内容は本編とは関係がなく、SpriteBuilderで配置したコンポーネントを扱いたいという内容をピンポイントで知りたい方のために書いております。

また、余った時間で`CCAction`を使った簡単なアニメーションをしてみます。

## 今回作るゲーム
今回はバルーンショットというゲームを作成する予定です。
もともと僕が作っている

![id995207358.png](https://qiita-image-store.s3.amazonaws.com/0/79216/c0a0da78-4bac-2257-9a1d-0594e953ba1e.png)
[Space Debris](https://itunes.apple.com/jp/app/id995207358)
というゲームの続編になります。

これをやっていただければどんなゲームを作ろうとしているか想像がつくかと思います。

# GameSceneのクラス名をつけます
[前回](http://qiita.com/syou007/items/9bebb01aff70dec0e3f3#spritebuilder%E3%81%A8xcode%E3%81%AE%E6%8E%A5%E7%B6%9A%E3%82%92%E7%A2%BA%E8%AA%8D%E3%81%99%E3%82%8B)を参考にして、`GameScene.ccb`のCCNodeに`GameScene`という`Custom class`の名前をつけてください。

# コンポーネントに名前をつけます
![1.png](https://qiita-image-store.s3.amazonaws.com/0/79216/0732375f-9311-90be-2509-c93828594562.png)
ここでは`_testLabel`とつけてます。

設定するのは`custom class`ではなく`Doc root var`に付与してください。
今回SpriteBuilderで行うのはこれだけになります。

# Sceneを格納するグループを作成します
![reup.png](https://qiita-image-store.s3.amazonaws.com/0/79216/e09d87cd-44d8-7b8c-2f0b-090d9a1eabe9.png)

強制することでは無いのですがグループを作る際には上記の図のようにフォルダを先に作ってドラッグすると

![3.png](https://qiita-image-store.s3.amazonaws.com/0/79216/6f26111c-8686-8715-45a3-59151b0dc7cf.png)

このようなダイアログボックスが表示されるので`Create Groups`を選択してグループを作成する。
そうすると、このグループにクラスファイル等を追加するとデフォルトでドラッグしたフォルダに作制してれるようになります。

## XCodeのグループは便利？
XCodeのグループは便利ですが、実際のフォルダと格納場所が違うため実ファイルを探す時に苦労します。
そういう時に困らないようにグループとフォルダをある程度合わせておくことをお勧めします。

クラスファイルはまだ良いのですが、大量のリソースファイル（画像とか）を管理する時は`Create folder references`で作成した方がプログラムコードからリソースを探しやすいです。
話が脱線してしまいますのでここでやめますが、XCodeのグループとはうまく付き合っていか無いと後々の保守性に関わってきます。（リクエストがあれば僕が遭遇したとんでもないプロジェクトについて書きます。）

# GameSceneを作ります。
![4.png](https://qiita-image-store.s3.amazonaws.com/0/79216/9fc1a65a-da3f-910d-1c8e-6f401629bc82.png)

先ほど作成したグループにクラスを作成します。
継承元は`CCNode`にしてください。
Cocos2dでは`CCNode`が全ての基底となってます。Cocoaでいう`UIView`と同じポジションにあります。
ちなみにCocoaでいう`UIViewController`に相当するものはCocos2dにはありません。`CCNode`が両方の役割を担ってます。

SpriteBuilderで作成するファイルの`Scene`も`Layer`も`CCNode`も全てSwiftでは`CCNode`として扱います。
`CCLayer`などは存在しません。（`CCScene`は存在しますが使う必要はないでしょう。SpriteBuilderが作成したMainSceneも`CCNode`を継承して作成されてます。）

# 文字を変えてみます。
GameSceneの中身を書き換えます。（import文は不要なので決して問題ありません。）

```lang:GameScene.swift
class GameScene: CCNode {
    // この変数にSpriteBuilderで作成したコンポーネントが差し込まれる。
    weak var _testLabel:CCLabelTTF!
    
    // 画面が生成後に同期で呼び出される。
    func didLoadFromCCB() {
        _testLabel.string = "置きかわる！"
    }
}
```
実行してみると、SpriteBuilderで作成したLabelの中身が置き換わっている事がわかると思います。
`_testLabel`は冒頭に`SpriteBuilder`で接続をした変数名で繋がってます。(weakキーワードがついている理由は[この記事](http://qiita.com/syou007/items/51f2342850e408739cc9)を読んでください。weakを知らない方は必読です！）

`didLoadFromCCB`はSpriteBulderで設定したコンポーネント全てが挿入された後に呼び出します。
GameSceneを作成する際に

```swift
CCBReader.loadAsScene("GameScene")
```

このようなコードを書いた事を覚えてますか？
これを誤って以下のように書いてしまうと何もないCCNodeが生成されてします

```swift
GameScene()
```

つまり`loadAsScene`が`GameScene`を生成してSpriteBuilderで設定したコンポーネントを挿入している事がわかると思います。

# おまけ
せっかくなので色々な事をしてみましょう。

## 傾ける
```swift
    func didLoadFromCCB() {
        _testLabel.rotation = 30.0  // 30度傾ける。
    }
```

## 大きくする。
```swift
    func didLoadFromCCB() {
        _testLabel.scale = 2.0  // 2倍
    }
```

## 2秒かけて傾ける
```swift
    func didLoadFromCCB() {
        _testLabel.runAction(CCActionRotateTo(duration: 2.0, angle: 30.0))
    }
```
Cocos2dのアニメーションは秀逸です。
CCActionを継承しているクラスを対象のCCNodeの`runAction`に引き渡すだけでアニメーションが発生します。
（CCActionクラスは使いまわせないので、各CCNodeに同じ動作をさせたい場合はその分CCActionのインスタンスを作成する必要があります。）

## 2秒かけて2倍の大きさにする。
```swift
    func didLoadFromCCB() {
        let action = CCActionScaleBy(duration: 2.0, scale: 2.0)
        _testLabel.runAction(action)
    }
```
actionを別の変数に入れて生成した例です。
CCActionの最後に`To`や`By`が付いているものがありますが、これは英語の意味そのままで

* `To`・・・現在の状態に関わらず、その状態に変化する。
* `By`・・・現在の状態からその状態に変化する。

よくわからない人は以下のコードを実行すればすぐに意味がわかると思います。

```swift
    func didLoadFromCCB() {
        _testLabel.scale = 2.0
        let action = CCActionScaleBy(duration: 2.0, scale: 2.0)
        _testLabel.runAction(action)
    }
```

```swift
    func didLoadFromCCB() {
        _testLabel.scale = 2.0
        let action = CCActionScaleTo(duration: 2.0, scale: 2.0)
        _testLabel.runAction(action)
    }
```

## 同時にActionを行う
```swift
    func didLoadFromCCB() {
        let action1 = CCActionScaleTo(duration: 2.0, scale: 2.0)
        let action2 = CCActionRotateTo(duration: 2.0, angle: 30.0)
        _testLabel.runAction(action1)
        _testLabel.runAction(action2)
    }
```

このように`runAction`を複数呼び出す事で同時に複数のアクションを実行させる事ができます。
また、以下のようにCCActionをまとめる事もできます。

```swift
    func didLoadFromCCB() {
        let action1 = CCActionScaleTo(duration: 2.0, scale: 2.0)
        let action2 = CCActionRotateTo(duration: 2.0, angle: 30.0)
        let action = CCActionSpawn(array: [action1, action2])
        _testLabel.runAction(action)
    }
```

動作は同じようになります。

## 順番にアクションを行う。
```swift
    func didLoadFromCCB() {
        let action1 = CCActionScaleTo(duration: 2.0, scale: 2.0)
        let action2 = CCActionRotateTo(duration: 2.0, angle: 30.0)
        let action = CCActionSequence(array: [action1, action2])
        _testLabel.runAction(action)
    }
```

ここまでくれば説明しなくても十分かと思います。

## アクションを止める。
上記で作成した`CCAction`を保持する事で

```swift
_testLabel.stopAction(action)
```

このようにしてアクションを止めれます。

## アクションの一時停止
```swift
_testLabel.paused = true
```

などと記載すれば一時的にアクションを停止できます。

# 次回は
[SpriteBuilderでアニメーションを作る](http://qiita.com/syou007/items/bdcd3921a033ed967016)手順をご説明します。
その素材をちょっと探してきます。。。気球と気球にぶら下がってるもの・・・。うーん。