Cocos2d v3 気球をランダムに生成して降らせる。

# 前回まで
* [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とSwiftのコンポーネント接続、様々なアニメーションについて](http://qiita.com/syou007/items/1c1a2b450cc93098495c)
* [SpriteBuilderでアニメーションを作る](http://qiita.com/syou007/items/bdcd3921a033ed967016)
* [SpriteBuilderで作ったオブジェクトをシミュレータに表示する](http://qiita.com/syou007/items/7492245b28133df94dd1)

これらを行いました。

# 今回のゴール
今回は気球をランダムに生成して、上から降らせていきます。

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

![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)
というゲームの続編になります。

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

# ランダムに気球を降らせてみます
気球は生成すれば勝手に落ちていくので、今回はランダムに気球を生成して落としていきます。
まずはコードを書きます。

```swift:GameScene.swift
class GameScene: CCNode {
    // 物理ノード
    weak var _physicsNode:CCPhysicsNode!
    
    // フレーム毎に呼び出されるメソッド
    override func update(delta: CCTime) {
        // ランダムに気球を生成します。
        if arc4random_uniform(100) == 0 {
            // バルーンを生成します。
            let balloonNode = CCBReader.load("Parts/BalloonNode")
            // 大きさをランダムにします。
            balloonNode.scale = Float(arc4random_uniform(25) + 25) * 0.01
            
            // 現在の大きさを取得します。
            let width = balloonNode.children[0].contentSizeInPoints.width * CGFloat(balloonNode.scale)
            let height = balloonNode.children[0].contentSizeInPoints.height * CGFloat(balloonNode.scale)
            
            // 上部へランダムに表示させます。
            balloonNode.position.x = CGFloat(arc4random_uniform(UInt32(self.contentSizeInPoints.width - width))) + width / 2
            balloonNode.position.y = self.contentSizeInPoints.height + height
            
            // 物理ノードにバルーンを設置
            _physicsNode.addChild(balloonNode)
        }
    }
}
```
お世辞にも良いコードとは言えませんが、第一弾のコードとしては十分だと思います。
このコードは機種依存コードなのでこのまま使う事は避けてください。
（端末のパフォーマンスによって挙動が変わります。回避コードは次回紹介致します。）

こちらを実行すれば今回のゴールは達成できます。
今回は上記のコードの解説をしていきます。

## updateメソッド
Updateメソッドは`CCNode`に用意されている（正しくは`CCSchedulerTarget`プロトコルで定義されている）メソッドです。
FPSの描画のタイミングに呼び出されます。

引数の`delta`は前に`update`メソッドが呼び出されてからどれくらい時間が経過したかを示す差分の時間が引き渡されます。
本コードが機種依存になっているのは、この`delta`を意識していないコードになっているためです。（機種によってupdateが呼び出される頻度に差が出ます。）

### FPSって？
FPSの説明は他のページを見た方が正確な情報が手に入ると思います。
拙いながら簡単に説明しておきます。

FPSは`Frames Per Second`の略称です。
OpenGLは一定の時間毎に画面を書き直す（レンダリング）事で画面が動いているように見せてます。
例えば`FPS=60`というのは1秒間に60回描画をしている事になります。
通常は`FPS=30`が出れば人間の目にはわからないので`FPS=30`が出れば大抵のゲームは問題なく動作します。

Cocos2dでFPSを確認したい場合は[こちら](http://qiita.com/syou007/items/1cd8b0d2deeb5acd38f1#cocos2d%E3%81%AE%E3%83%87%E3%83%90%E3%83%83%E3%82%B0%E6%83%85%E5%A0%B1%E3%82%92%E5%87%BA%E3%81%97%E3%81%9F%E3%81%84%E5%A0%B4%E5%90%88)をみてください。

自前でFPSを管理すると

* どれくらいのタイミングで呼べば良いか？
* 描画処理と計算処理を別にすべきか？

などの問題を解決しなければなりませんが、Cocos2dを使っていればupdateメソッドだけである程度解決できます。
（updateメソッドで解決できないレベルのゲームを作った事がないのでupdateメソッドだけで解決できない場合の回避策は知りません。。。）

## arc4random_uniformメソッド
[こちら](http://tanukichi566.blog.fc2.com/blog-entry-57.html)の解説ページにわかりやすく書かれてます。
上記参考サイトの理由により`rand()`を使わずに`arc4random_uniform()`を使用して、乱数を発生させてます。

updateメソッドが呼び出されるたびに0〜99の乱数を発生させ、0が出た場合に気球を出現させてます。
すなわち、1/100で気球が発生してます。

## balloonNode.scale
元の気球が大きい画像のため、大きさを変更してます。

```swift
Float(arc4random_uniform(25) + 25) * 0.01
```

0.25〜0.5(正確には0.25〜0.49)の大きさの乱数を発生させて、縮小して気球を生成してます。
乱数で大きさを変えているのは狙いにくい気球と狙いやすい気球を作るためです。

## 配置
実際の配置は以下の処理で行ってます。

```swift
            // 現在の大きさを取得します。
            let width = balloonNode.children[0].contentSizeInPoints.width * CGFloat(balloonNode.scale)
            let height = balloonNode.children[0].contentSizeInPoints.height * CGFloat(balloonNode.scale)
            
            // 上部へランダムに表示させます。
            balloonNode.position.x = CGFloat(arc4random_uniform(UInt32(self.contentSizeInPoints.width - width))) + width / 2
            balloonNode.position.y = self.contentSizeInPoints.height + height
            
            // 物理ノードにバルーンを設置
            _physicsNode.addChild(balloonNode)
```

balloonNode自体にはContentSizeを設定してないので、子要素の1番目のサイズを取得してscaleに合わせたサイズを取得します。(CGSizeで取得しても良いのですが、アクセスがここだけなので簡略化してます。)
今回はこのようなコードで取得してますが、最終的には`children[0]`というコードは無くす予定です。

あとは画面上部に表示させます。
前回は`didLoadFromCCB`で処理をしてたので`self.contentSizeInPoints`が取得できませんでしたが、今回は`update`内部なので`self.contentSizeInPoints`を取得して計算をしてます。
左右の画面外にでないように配置して、画面の上部に隠れるように配置してます。

これで気球が落ちてきます。

## オブジェクトを消していない。
コードを書いていると気付くと思いますが、気球は下に落ちたあともオブジェクト自体は消えてません。
なので、このプログラムを動かし続けるとメモリがどんどん増えていきます。

今回のゲームでは気球が一番下まで落ちたらゲームオーバーにする予定なので、これはこのままでいいです。

# 次回は
気球は落ちてくるようになりましたが、気球同士が重なってしまいます。
[次回は](http://qiita.com/syou007/items/b480c5e82a1658da3ee4)この回避方法について説明します。


# このゲームもよろしくお願いいたします。
![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)
気軽に楽しめると思うので、ぜひよろしくお願いいたします！

DLLしていただけると励みになります！