今回はCocos2d向けUI作成ツール「CocosBuilder」を使ってマルチ解像度対応したUIを作っちゃおう!な内容を書きます。Cocos2d-xのセットアップが未だな場合は前回エントリーを参照ください。
実施環境
- CocosBuilder 3.0 α5
- Cocos2d-x 2.1.4
今回の目標
CocosBuilderを使ってiOS/Android向けにマルチ解像度に対応したUIを作成する。
CocosBuilderをインストール
CocosBuilderページからどうぞ。利用しているCocos2d-xのバージョンと対になるCocosBuilderのバージョンが存在する為、よくバージョン番号を確認してからダウンロードしてください。
CocosBuilder上でUI専用プロジェクトを新規作成
- CocosBuilderを起動
- メニュー上の「File > New > Project」を選択
- 新規プロジェクト名を設定してCocos2d-xで作成したプロジェクト内に作成*1
- 新規作成したプロジェクト内の「Resources」フォルダ内にはテンプレUIがありますが、邪魔になるので全て削除
- Cocos2d-xで作成したプロジェクト直下にある「Resources」ディレクトリを削除
UI専用プロジェクトの設定変更
- メニュー上の「File > Publish Settings」を選択
- HTML5のチェックを外し、Androidにチェックを入れる*2
UIファイルを新規作成
今回は横向きの画面を作成します。
- メニュー上の「File > New > Interface File」を選択
- 「Create a new Document」ダイアログが表示され、CocosBuilder上での表示解像度を選ばされます。今回は「iPhone Landscape」にチェックが付いている状態のまま「Create」ボタンを押下
- 初回起動させるUIファイル名は「MainScene」と付けます。他の名前を設定したい場合は「メニュー > Project Settings」を選択して「Start ccb-file name」の設定を変更する必要があります
- UIプロジェクトの「Resources」ディレクトリ内にファイル作成*3
表示解像度の変更/切り替え
「Create a new Document」ダイアログ上で設定した表示解像度は、CocosBuilderのメニューにある「Document > Edit Resolutions」から編集できます。表示解像度の種類を増やすとメニューにある「Document > Resolutions」から表示解像度毎の見た目に切り替えて確認できます。
UI作成
- 画像をUI上に配置する場合「UIプロジェクト > Resources」直下に「resources-auto」ディレクトリを作成し、このディレクトリ内に画像を追加していきます。なお、追加する画像はUIファイル作成時に設定したスケールがベースサイズ(scale 4.0)となる
- 適当に作成。今回は分かりやすいように上下左右中央にCCSpriteを配置
- メニュー上の「File > Save」を選択してUIファイルを保存
- メニュー上の「File > Publish」を選択してCocos2d向けのファイルを生成
UI読み込み
Cocos2dxで作成したプロジェクト内の「Classes > AppDelegate.cpp」を開いて「AppDelegate::applicationDidFinishLaunching」メソッド内に以下のコードを追加します。なお、今回は横向きを想定しての数値設定な為、もし縦向き対応させる場合は縦横の設定値を全て逆にする必要がある
bool AppDelegate::applicationDidFinishLaunching()
{
CCDirector *pDirector = CCDirector::sharedDirector();
pDirector->setOpenGLView(CCEGLView::sharedOpenGLView());
CCSize designSize = CCSizeMake(480, 320);
CCSize resourceSize;
CCSize screenSize = CCEGLView::sharedOpenGLView()->getFrameSize();
std::vector<std::string> searchPaths;
std::vector<std::string> resDirOrders;
TargetPlatform platform = CCApplication::sharedApplication()->getTargetPlatform();
if (platform == kTargetIphone || platform == kTargetIpad) {
searchPaths.push_back("Published-iOS");
CCFileUtils::sharedFileUtils()->setSearchPaths(searchPaths);
if (screenSize.height > 768) {
resourceSize = CCSizeMake(2048, 1536);
resDirOrders.push_back("resources-ipadhd");
} else if (screenSize.height > 640) {
resourceSize = CCSizeMake(1536, 768);
resDirOrders.push_back("resources-ipad");
} else if (screenSize.height > 480) {
if (screenSize.width < 1536) {
resourceSize = CCSizeMake(1136, 640);
} else {
resourceSize = CCSizeMake(960, 640);
}
resDirOrders.push_back("resources-iphonehd");
} else {
resourceSize = CCSizeMake(480, 320);
resDirOrders.push_back("resources-iphone");
}
CCFileUtils::sharedFileUtils()->setSearchResolutionsOrder(resDirOrders);
} else if (platform == kTargetAndroid) {
if (screenSize.height > 1200) {
resourceSize = CCSizeMake(1200, 800);
resDirOrders.push_back("resources-xlarge");
} else if (screenSize.height > 960) {
resourceSize = CCSizeMake(960, 640);
resDirOrders.push_back("resources-large");
} else if (screenSize.height > 480) {
resourceSize = CCSizeMake(720, 480);
resDirOrders.push_back("resources-medium");
} else {
resourceSize = CCSizeMake(568, 320);
resDirOrders.push_back("resources-small");
}
CCFileUtils::sharedFileUtils()->setSearchResolutionsOrder(resDirOrders);
}
pDirector->setContentScaleFactor(resourceSize.width / designSize.width);
CCEGLView::sharedOpenGLView()->setDesignResolutionSize(designSize.width, designSize.height, kResolutionFixedHeight);
pDirector->setDisplayStats(true);
pDirector->setAnimationInterval(1.0 / 60);
ScriptingCore* sc = ScriptingCore::getInstance();
sc->addRegisterCallback(register_all_cocos2dx);
sc->addRegisterCallback(register_all_cocos2dx_extension);
sc->addRegisterCallback(register_all_cocos2dx_extension_manual);
sc->addRegisterCallback(register_cocos2dx_js_extensions);
sc->addRegisterCallback(register_CCBuilderReader);
sc->addRegisterCallback(jsb_register_chipmunk);
sc->addRegisterCallback(jsb_register_system);
sc->addRegisterCallback(JSB_register_opengl);
sc->addRegisterCallback(MinXmlHttpRequest::_js_register);
sc->addRegisterCallback(register_jsb_websocket);
sc->start();
CCScriptEngineProtocol *pEngine = ScriptingCore::getInstance();
CCScriptEngineManager::sharedManager()->setScriptEngine(pEngine);
ScriptingCore::getInstance()->runScript("main.js");
return true;
}
コードはCocosBuilderのメニュー上の「Help > CocosBuilder User Guide」の「4c」とほぼ同じです。リソースの読み込み先を指定し、端末解像度に合わせてUIをスケールさせてます。
スケール方法
CCEGLView::sharedOpenGLView()->setDesignResolutionSize は最後の引数に設定する値はスケール方法となっており以下の値が設定可能です
値 |
意味 |
kResolutionExactFit |
画面比率を無視して、端末解像度に合わせて設定する。はみ出しや余白が生じない |
kResolutionNoBorder |
画面比率を維持して、端末解像度いっぱいに設定する。縦横のどちらかがはみ出る |
kResolutionShowAll |
画面比率を維持して、端末解像度に合わせて設定する。縦横のどちらかに余白が生じる |
kResolutionFixedHeight |
画面比率を維持して、端末解像度の高さに合わせて設定する。横がはみ出しや余白が生じる |
kResolutionFixedWidth |
画面比率を維持して、端末解像度の幅に合わせて設定する。縦がはみ出しや余白が生じる |
別のUIファイル読み込み方法
上記サンプルコードは「main.js」を読み込む事で「MainScene.ccbi」を読み込んでいます。jsを介さなくても以下のようにcpp側からccbiファイルを直接読み込むことが出来ます。
cocos2d::extension::CCNodeLoaderLibrary *lib = cocos2d::extension::CCNodeLoaderLibrary::newDefaultCCNodeLoaderLibrary();
cocos2d::extension::CCBReader *reader = new cocos2d::extension::CCBReader(lib);
CCScene *scene = reader->createSceneWithNodeGraphFromFile("MainScene.ccbi");
pDirector->runWithScene(scene);
- Cocos2d-xで作成したプロジェクトをXcodeで起動
- プロジェクト上から「Resources」を削除
- UIプロジェクト内の「Published-iOS」フォルダを追加。フォルダ追加の際に「Folders」項目を「Create folder references for any added folders」に設定しておくと楽できます*4
- Buildして端末上で確認
assetsへ必要ファイルをコピーさせる
Cocos2dxで作成したプロジェクト内の「proj.android > build_native.sh」をテキストエディタで開き、以下のように置き換えます。
cp -rf "$APP_ROOT"/Resources/* "$APP_ANDROID_ROOT"/assets
cp -rf "$APP_ROOT"/(UI専用プロジェクト名)/Published-Android/* "$APP_ANDROID_ROOT"/assets
実行
- Cocos2d-xで作成したプロジェクトをAndroidで起動
- Buildして端末上で確認
まとめ
iOSはシミュレータでだいたい大丈夫そうなのが分かりましたが、Androidはそんなに確認してないので今回の方法だと問題あるかも...