WonderPlanet DEVELOPER BLOG

ワンダープラネットの開発者ブログです。モバイルゲーム開発情報を発信。

CocosBuilderを使って素早く画面を作成する

こんにちは、デザイナーの上松です。

Cocos2d-xでは、ゲームを作るための機能がよくまとめられているため、とても効率良くプログラムが作れます。
しかし、ことレイアウト作業はとても煩雑です。
微修正とコンパイルを繰り返すのは時間の無駄でしかありません!

そこで、InterfaceBuilderならぬCocosBuilderの登場です。
このCocosBuilderは、Cocos2dのレイアウトを作成するためのGUIツールで、プログラムで作業する数十倍は効率よく画面レイアウトや機能を作ることができます。
CocosBuilderで作成したccbiファイルを読み込む機能はCocos2d-xでも利用できるため、Cocos2d-xでもこの恩恵を授かることが可能です。

▼最新版は以下のサイトから
http://cocosbuilder.com

デザインツールとしては微妙に使い勝手が悪かったりしますが、GitHubからソースをクローンすればカスタマイズすることも可能です。
弊社でも積極的にカスタマイズを行っており、大量のディレクトリがある場合に動作しない問題の解決や、タイムラインの遷移再生、インスペクタの改造など、より実用的なツールとして稼働しています。

この記事では簡単な確認ダイアログを作ってみようと思います。
レイアウト、組み込み、プログラムとの連携などの一連の作業を追い、簡単なシーンを作ってみましょう。

1.CocosBuilderを使ってダイアログを作る

・プロジェクトを作ります。

1

~/CocosBuilderProject/
というフォルダに、CCBという名前のプロジェクトを作成しました。

2

左下の+ボタンからNew Interface File..を選びます。
ダイアログという、ゲーム内のパーツを作りますので、Full screenのチェックを外します。
Root object typeはCCNodeにしておきます。

3

CocosBuilderで作成するインターフェースファイルはResources内にしか保存できませんので、ひとまずResources直下に保存します。

プロジェクトの設定もしておきます。デフォルトではJavaScript用の設定になっています。
以下のようにチェックを外します。

5

6

それではレイアウトを作成します。
以下のようなPNGファイルを用意したので、こちらをResouces内に保存します。左ペインのProjectツリーに表示されたと思いますので、ドラッグアンドドロップで配置します。
座標は0,0に合わせます。

新規CCLabelTTFを配置します。

7

適当なサイズと色に設定したら、次にボタンを作ります。
CCMenuを作成し、その中に、CCMenuItemImageを二つ配置しましょう。

こんな感じになりました。とりあえずCocos2d-xで表示するために一旦出力します。

9

このように設定をして、Command+Alt+Sでパブリッシュします。
次にこれを表示するCocos2d-xプロジェクトを作ります。

2. Xcodeで動かしてみる

Xcodeで新しくCocos2d-xプロジェクトを作成します。
XcodeのResources内に、リソースを追加します。

CocosBuilderのResourcesファイルをすべてXcodeのResourcesに放り込みます。
パブリッシュされたccbiファイルも追加します。

10 (選択したものをすべて追加)

HelloWorldScene.hに移動し、以下を追記します。

冒頭部

#include "cocos-ext.h"  
using namespace cocos2d::extension;  

HelloWorldScene.cpp、initメソッド最下部に以下を追加します。

CCNode* node = NULL;  
  
CCNodeLoaderLibrary* ccNodeLoaderLibrary = CCNodeLoaderLibrary::sharedCCNodeLoaderLibrary();  
CCBReader* ccbReader = new CCBReader(ccNodeLoaderLibrary);  
ccbReader->autorelease();  
  
//Read CCBI File  
node = ccbReader->readNodeGraphFromFile("myDialog.ccbi");  
node->setPosition( ccp(size.width/2, size.height/2) );  
this->addChild(node);  

これで実行します。

11

動きましたでしょうか?
メニューもタップで動作することが確認できるかと思います。

この通り、レイアウトを組み込む作業は大変簡単になっています。
次に、ルートノード用のCustomClassを作成して、テキストを設定したり、タップイベントを取得するようにしてみましょう。
CocosBuilderに戻ります。

3. カスタムクラスと変数設定で、プログラムと連携準備!

CocosBuilderで作ったノードに機能をつけたい場合、Custom Classを設定します。
この場合、作ったccbファイルをDialogクラスとして使用したいので、ルートにあるCCNodeにカスタムクラスとして「Dialog」と入力します。

12

次に、テキストを自由に設定したいので、ルートのメンバ変数としての設定を行っておきます。
作ったCCLabelTTFノードに、「text」というメンバ変数名を設定します。

13

Doc root varは、このドキュメントのルートオブジェクト(先ほどカスタムクラスを設定したノード)のメンバ変数としてロードする設定です。

14

また、ボタンにイベントとタグを付けておきましょう。
buttonTappedというセレクタを設定します。ターゲット(イベントを受け取るオブジェクト)は、Document rootにしておきます。
また、CCNodeの項目の中に、それぞれ任意のタグを設定しておいてください。

この状態で、保存してパブリッシュし、ccbiを上書きしましょう。
この設定だけで終われば便利なのですが、プログラム側では受け入れ準備として、
カスタムクラスのためのローダーと、メンバ変数設定を実際のメンバ変数へ、またセレクタ名を実際のセレクタにアサインする作業が必要になります。

4. カスタムクラスとローダーを作成して、受け入れ態勢を整える

Xcodeに戻ります。
先述の通り、カスタムクラスを使用するためには、カスタムクラスとそのカスタムクラスをロードするためのLoaderを作成しなければいけません。
とはいえ難しいものではないのでさくっと作ってしまいましょう。

まず、Dialogクラスを作成します。
今回は便宜上、HelloWorldScene.hとHelloWorldScene.cppに記述します。

HelloWorldScene.h

class CC_DLL Dialog :  
public CCLayer,  
public CCBSelectorResolver,  
public CCBMemberVariableAssigner  
{  
public:  
    CREATE_FUNC(Dialog);  
    virtual bool init();  
  
    /* Accessor */  
    void setText(const char* str);  
  
    /* Action */  
    void buttonTapped(CCObject* pSender);  
  
    /* CCB Connector */  
    virtual bool onAssignCCBMemberVariable(CCObject* pTarget, const char* pMemberVariableName, CCNode* pNode);  
    virtual SEL_MenuHandler onResolveCCBCCMenuItemSelector(CCObject * pTarget, const char* pSelectorName);  
    virtual SEL_CCControlHandler onResolveCCBCCControlSelector(CCObject * pTarget, const char* pSelectorName){ return NULL; };  
protected:  
    CCLabelTTF* m_pText;  
};  
  
//ローダークラス  
class DialogLoader : public CCLayerLoader {  
public:  
    CCB_STATIC_NEW_AUTORELEASE_OBJECT_METHOD(DialogLoader, loader);  
protected:  
    CCB_VIRTUAL_NEW_AUTORELEASE_CREATECCNODE_METHOD(Dialog);  
};  

SEL_CCControlHandlerは、今回使いません。
次に、実装部です。

/* Dialogクラス */  
bool Dialog::init(){  
    if(! CCLayer::init()){  
        return false;  
    }  
  
    return true;  
}  
  
void Dialog::setText(const char* str)  
{  
    if(m_pText){  
        m_pText->setString(str);  
    }  
}  
  
/* Action */  
void Dialog::buttonTapped(CCObject *pSender)  
{  
    CCLOG("Button Tapped: %d", ((CCNode*)pSender)->getTag());  
}  
  
/* Code Connections*/  
bool Dialog::onAssignCCBMemberVariable(CCObject* pTarget, const char* pMemberVariableName, CCNode* pNode) {  
    CCB_MEMBERVARIABLEASSIGNER_GLUE(this, "text", CCLabelTTF*, m_pText);  
    return true;  
}  
  
SEL_MenuHandler Dialog::onResolveCCBCCMenuItemSelector(CCObject * pTarget, const char* pSelectorName)  
{  
    CCB_SELECTORRESOLVER_CCMENUITEM_GLUE(this, "buttonTapped", Dialog::buttonTapped);  
    return NULL;  
}  

HelloWorld::initを修正します。

    CCNodeLoaderLibrary * ccNodeLoaderLibrary = CCNodeLoaderLibrary::sharedCCNodeLoaderLibrary();  
    ccNodeLoaderLibrary->registerCCNodeLoader("Dialog", DialogLoader::loader()); // <----ここを追加  
    CCBReader * ccbReader = new CCBReader(ccNodeLoaderLibrary);  

 

    //Read Files  
    node = ccbReader->readNodeGraphFromFile("myDialog.ccbi");  
    node->setPosition( ccp(size.width/2, size.height/2) );  
  
    ((Dialog*)node)->setText("こんにちは"); // <---ここを追加  
  
    this->addChild(node);  

エラーがないことを確認して実行します。

15

見事動きました。

このような連携で、シーンをどんどん組み上げていくことが可能です。
パーツ単位でCocosBuilderのプロジェクトを作ることで、パーツ単位でのレイアウト、デザインの変更、アニメーションの修正などが非常に楽になります。

面倒な作業はソフトにおまかせし、スピーディーにプロジェクトを進めましょう!