テンプレートプロジェクトの解説
第1回では、Cocos2d-xの新規プロジェクトを作成し、テンプレートプロジェクトを実行しました(図3-1)。こちらを利用して、プロジェクトの構成やソースコードなどを解説したいと思います。
プロジェクトの構成
第1回で作成したプロジェクト名は「NewProject」でした。そのプロジェクト名と同名のフォルダの中は、図3-2のような構成になっています。
「Classes」フォルダには、ゲームを構成するソースコードが格納されています。今回は開発言語にC++を選択しましたので、各クラスを構成するためのヘッダファイル(拡張子:h)と実装ファイル(拡張子:cpp)が、AppDelegateクラスとHelloWorldクラスに対して用意されています。AppDelegateクラスは、ゲーム起動時において、Cocos2d-xの準備ができたら最初に呼び出される関数が用意されているクラスです。またHelloWorldクラスは、図3-1で示した画面を構成するクラスです。ゲームのために用意するソースコードは、この「Classes」フォルダに追加するようにしてください。
「Resources」フォルダには、ゲームを構成する画像・フォントファイルなどのリソースが格納されています。例えば「background.png」ファイルは、図3-1の画面の中央に表示されているものです。ゲームのために用意する画像は、この「Resources」フォルダに追加するようにしてください。またBGMやSEなどの音声ファイルを含めることもできます。
「proj.android」「proj.ios_mac」など「proj.xxx」は、各OSに対応したプロジェクトフォルダです。例えば「proj.android」は、Android用のプロジェクトが格納されています。また「proj.ios_mac」には、iOSとMac OS用のプロジェクトが格納されています。すべてのプロジェクトは、「Classes」と「Resources」フォルダを参照していますので、基本的にこれらを利用するようにしましょう。
AppDelegateクラス
Cocos2d-xを利用してゲームを作成した場合、ゲームを起動すると最初にCocos2d-xの準備が行われます。そしてCocos2d-xの準備が終わると呼び出されるのが、AppDelegateクラスのapplicationDidFinishLaunching関数です。その関数は「AppDelegate.cpp」に記述されています。この関数では、OpenGL ESの初期化、デバッグ情報の表示制御、フレームレートの設定などの重要な処理を行っていますが、ここでは最初に表示する画面(HelloWorldクラス)を指定する処理に絞って解説したいと思います。下記のソースコードは、画面表示に必要なもののみを抜き出しています。また日本語の簡単なコメントを追加しました。
//Directorクラスのインスタンスを取得する auto director = Director::getInstance(); //HelloWorldクラスのインスタンスを生成する auto scene = HelloWorld::createScene(); //HelloWorld画面を実行する director->runWithScene(scene);
先に述べたように、Directorクラスはシングルトンパターンです。Directorクラスの唯一のインスタンスを取得するため、2行目のようにDirectorクラスのgetInstance関数を実行し、director変数へ格納しました。ここでauto型が見られますが、これはC++11の機能です。つまり、Cocos2d-xではC++11を利用することができます。追々説明しますが、C++11のラムダ式も便利であり、Cocos2d-xでもよく利用されています。
この後説明するHelloWorldクラスでは、createScene関数がSceneクラスのインスタンスを返します。それを5行目のようにscene変数に格納します。
画面遷移を管理するのは、Directorクラスの役割でした。ゲーム起動後、最初に表示する画面の指定は、8行目のようにDirectorクラスのrunWithScene関数により行われ、表示するHelloWorld画面、つまりscene変数を引数として渡します。
これでゲームの最初の画面として、HelloWorld画面が表示されます。
HelloWorldクラス
これまで紹介するうえで、HelloWorld画面とHelloWorldクラスという言葉を使っていたため、HelloWorldクラスがSceneクラスのサブクラスと思った方も多いのではないでしょうか。「HelloWorldScene.h」に定義されているように、実はHelloWorldクラスはLayerクラスのサブクラスです。その中で、createScene関数を用意し、HelloWorldクラスのインスタンスが含まれるSceneを返しています。その他HelloWorldクラスには、初期化するためのinit関数、メモリを気にすることなくインスタンスを生成できるcreate関数(CREATE_FUNCマクロ関数で定義)があります。
ここでは、実際に画面を構成しているinit関数に注目して解説しましょう。このinit関数は、インスタンスが生成された後、最初に呼び出される関数です。「HelloWorldScene.cpp」に記述されているinit関数を見てみましょう。
//スーパークラスの初期化
if ( !Layer::init() )
{
//初期化に失敗した場合はfalseを返す
return false;
}
init関数が呼び出された直後に、スーパークラスであるLayerクラスのinit関数を呼び出しています。Nodeクラスを継承しているときは、必ずinit関数を呼び出すようにしましょう。初期化に失敗した場合は、戻り値としてfalseを返します。
HelloWorldクラスのinit関数内では、MenuItemImageクラスとMenuクラスを利用したボタンを表示する処理が行われていますが、もっと簡単なボタンクラスがありますので、トランプゲームを作る中で説明したいと思います。そのため、ここではボタンの説明を省きます。次は、ラベルの表示方法を見ましょう。
//フォントを指定したラベルの作成
auto label = Label::createWithTTF("Hello World", "fonts/Marker Felt.ttf", 24);
//ラベルの位置を指定
label->setPosition(Vec2(x, y));
//レイヤーにラベルを表示する
this->addChild(label, 1);
ラベルには、Labelクラスを利用します。ラベルの生成方法はいろいろありますが、ここでは文字列・フォントファイル・フォントサイズを指定したcreateWithTTF関数を利用します。2行目のように、第1引数に表示する文字列である「Hello World」、第2引数に「Resources/fonts」フォルダに格納されている「Marker Felt.ttf」のパス、第3引数にフォントサイズをそれぞれ渡します。Labelクラスのインスタンスが生成されるので、label変数に格納します。
ラベルの表示位置は、5行目のようにsetPosition関数を利用します。その引数について、ここでは理解しやすくするため「Vec2(x, y)」と表示していますが、Vec2とはx方向とy方向の座標を指定します。また「x」と「y」にはそれぞれ数値が入ります。
そして8行目のようにaddChild関数を利用して、HelloWorldクラスのレイヤーにラベルを表示しています。ここで、addChild関数の第2引数は、Zオーダーを示します。Zオーダーとは、画面の表示順を表しており、大きな数値ほど手前に表示されます。たった3行のソースコードで、ラベルを表示することができました。
//HelloWorld.pngを読み込みスプライトを生成する
auto sprite = Sprite::create("HelloWorld.png");
//スプライトの位置を指定
sprite->setPosition(Vec2(x, y));
//レイヤーにスプライトを表示する
this->addChild(sprite, 0);
先に説明したように、画像の表示にはSpriteクラスを利用します。Spriteクラスのインスタンス生成もいろいろありますが、ここでは引数にファイルパスを持つcreate関数を利用します。「HelloWorld.png」の画像を表示するので、文字列として「HelloWorld.png」を渡しています。そして、インスタンスをsprite変数に渡します。位置の指定は、先ほどのラベルと同じsetPosition関数を利用します。また画面に表示するため、addChild関数の引数にsprite変数を渡しています。たったこれだけで、画像を画面に表示することができました。

