cocos2d-xに入門したお話


ずうっと前からやるやる詐欺してたのをやめようと思い入門したお話。

- cocos2d-xのダウンロードからこちらの[チュートリアル](http://www.drjiro.com/cocos2d-x/)を+α。
- これを書いた時点でのcocos2d-xのバージョンは3.3
- チュートリアルで作ったものは[Github](https://github.com/utah-KT/myFirstCocos2dx)に。
- バージョンの違いかチュートリアルに書かれたとおりにやって上手く行かなかったところがあったので書いておきます。

##DownLoad 〜 Xcode でプロジェクトを編集できるようになるまで

[Github](https://github.com/cocos2d/cocos2d-x)にリポジトリがあるのでそこからとってくる。
したらREADMEに従ってcocosスクリプトを使える状態にする。

プロジェクトの作成は以下のとおり。

```console
$ cocos new myFirstCocos2dx -p com.utah.myFirstCocos2dx -l cpp -d ./
```

スクリプトによって作成されたディレクトリ/proj.ios_mac 以下にXcodeプロジェクトファイルがあるのでそれをXcodeで開く。


##基本的なとこ
###cocos2d-xの概念
- Directorというクラスが存在し、これを介してSceneやSprite等を操作する。
- アプリケーションの画面はSceneとSpriteから構成される。
	- 参照したチュートリアルにはこれにLayerが含まれていたけれど、[Wiki](http://www.cocos2d-x.org/wiki/Layer)によるとLayerはそのうちなくなるらしい。
- Sceneはひとつの画面に対応する。ゲームで例えるのならばタイトル画面、プレイ画面、リザルト画面とか。
	- 画面が遷移する度にSceneも入れ替わっていく。
- Spriteには画像やアニメーションを入れることができる。
- Sceneの上にSpriteを乗っけていって画面を構成する。

###書き方

- Classes以下にcpp,headerを追加していくことになる。既にHelloWorldプログラムが入っているので、作成した時点ですぐに実行、動作確認が可能。
- 画像とかはResourcesにつっこむ。
- AppDelegateクラスのapplicationDidFinishLaunching関数がアプリ起動後に呼び出されるので、そこからコードを書いていく。

以下コード例

- Directorを取得して最初のSceneを始めるまで

```
// 初期化
auto director = Director::getInstanse();

// GLView の作成
auto glbiew = director->getOpenGLView();
    if(!glview) {
        glview = GLViewImpl::create("My Game");
        director->setOpenGLView(glview);
    }

    // Sceneの作成
    auto scene = HelloWorld::createScene();
    // 作成したSceneの実行
    director->runWithScene(scene);

```

- シーン入れ替え

```
    Director::getInstance()->replaceScene(nextScene);
```

- スプライトの追加

```
    scene->addChild(sprite);
```

- スプライトにアニメーションを持たせる

```
    // キャッシュ取得。
    auto cacher = SpriteFrameCache::getInstance();
    // アニメーションに使う画像情報を持つplistを読み込む。
    cacher->addSpriteFramesWithFile("anime.plist");
    
    // 使用する画像を持つスプライトをベクタに詰めてく。
    Vector<SpriteFrame> frames;
    frames.pushBack(cacher->getSpriteFrameByName("texture.png"));

    // アニメーション作成。第二引数で指定した秒数毎に画像を更新する。
    auto animation = Animation::createWithSpriteFrames(frames,0.1f);
    // Animate作成。AnimationはActionを継承していないのでそのままではActionとしてSpriteに登録できない。
    auto action = Animate::create(animation);
    // 繰り返し回数の設定されたアクションにする。この場合は∞。
    auto infAction = RepeatForever::create(action);

    //スプライトに登録して実行。
    sprite->runAction(infAction);
    
```


##チュートリアルの通りにやって上手く動かなかった箇所
v3.0からv3.3で変更があったのかチュートリアルに記載されているコードでは上手く動かなかった箇所があったのでそのメモ。

```5章.作成したspriteからサイズを取得する箇所
// 元のコード
// 単にcreateするとgetContentSize()で正しいサイズが得られない。
// sprite = Sprite::create(); 

//アニメーション作成時に使ったスプライトフレームを使うと大丈夫。
sprite = Sprite::createWithSpriteFrame(frames.front());

auto contentSize = sprite->getContentSize();

```

```6章.PlaySceneクラスにupdate関数を追加する箇所
// 元のコード
// このままだと起動時に一瞬ランナーが浮く (レイヤーとプレイヤー二つ分の高さが初期位置になってしまうため？)
// gameplayLayer->setPosition(-eyeX, Global::g_groundHeight);

// Layerを地上高で固定する意味はないからこれが正しい
gameplayLayer->setPosition(-eyeX, 0);
```

8章.イベントリスナーの削除

- 解説にはPlaySceneでLayerを初期化した直後に削除とあるが正しくはPlayScene初期化直前なのでは…？
- Layer初期化後に削除するとその後ゲーム中にリスナを登録することがないのでタッチを受け付けない。
- また、PlaySceneでonCollisionBeginを登録した後に削除すると衝突が起きなくなる。
- こう書くのは少し乱暴って書いてあったけど綺麗に書くのならどうするのが正しいのだろう。

##音の付け方
参照したチュートリアルでは音楽について触れていなかったので。BGM,効果音の付け方。

cocos2d-xでは効果音、BGMの操作にSimpleAudioEngineを使う。

使用するメソッドは playBackgroundMusic, playEffect のように、命令 + BGMか効果音かとなっている。


```
// ヘッダファイルのインクルードと名前空間を使用する宣言が必要。
#include "SimpleAudioEngine.h"
using namespace CocosDension;

// インスタンスの取得。
auto audio = SimpleAudioEngine::getInstance();

// プリロード
audio->preloadBackgroundMusic("bgm.wav");
audio->preloadEffect("fx.wav");

// 再生。第二引数はループするかどうか。trueでループし、省略するとfalseとなる。
audio->playBackgroundMusic("bgm.wav",true);
// エフェクトの場合idが帰ってくる。一時停止等する際にこのidを使う。
int id = audio->playEffect("fx.wav");

// 停止。BGM側の引数はメモリを開放するかどうか。trueで開放。
audio->stopBackgroundMusic(true);
audio->stopEffect(id);

// 一時停止。
audio->pauseBackgroundMusic();
audio->pauseEffect(id);

// 一時停止からの再開。
audio->resumeBackgroundMusic();
audio->resumeEffect(id);
```


##まとめ
チュートリアルやっただけだけど結構書きやすくていいかなと思った。簡単なものならば時間もさほどかからなさそうだし何か思いついたら書いていきたいところ。

v3.0向けのチュートリアルのコードがv3.3では正しく動作しなかったと考えると結構cocos2d-xはがしがし更新されていくものなのかもしれない。

Layerが将来的になくなるとか、LabelTTFが非推奨とかはチュートリアル途中で知ったので作ったものには残ってしまっている…。非推奨なクラスを使用しないように書き換えるところまでやりきったほうがいいかもしれない。

…とも思ったけどそれやるくらいなら別にアプリケーションを作ってそこで習得していくのが良さそう。

次cocos2d-xで記事書くときは自分で考えた何かを書いていて得たことを書ければと！