Edited at

Cocos Studio2を触ってみた

More than 3 years have passed since last update.

CYBIRDエンジニア Advent Calendar 2015 17日目の@doidoidonです。

今年は暖冬のうちにいつの間にかもうすぐクリスマスですねー。昨年も色々開発プロジェクトでもがきながら、Advent Calender2014の記事を投稿したのを思い出しました。最近はあまりコードを書くこともなく会議三昧の毎日なので、久々にエンジニアっぽい記事を書くことに少し気持ちが高揚してます。

昨日はサイバードのデータ分析基盤を支えるカリスマリードエンジニア@yuichi_komatsuさんのEmbulkとBigQueryが黄金コンビすぎる話でした。なかなかつぼを押さえた検証と考察の中に、データ分析アーキテクチャーをキャプテン翼くんの登場キャラクターで例えるという、ひときわ光るたとえ話を織り交ぜ、他の追随を許さないテイストに仕上がってましたねー


本日の内容

最近社内で参加者の持ち回り講師の形でCocos2d-xの勉強会を行ってまして、Cocosアプリなど作ったことのない自分はありがたくもCocos Studioの使い方について講義することを拝命しましたので、ちょこちょこ勉強した内容をここにこっそり発表したいと思います。


Cocos Studioとは

Cocos Studioとは、公式で提供されているUIエディターです。

CocoStudioLogo.png

GUI操作でレイアウトを組み立て、調整することができる便利なツールなので、仕様書見ながらエンジニアがミリミリ各オブジェクトのサイズや座標調整をやる必要がなくなります。思えば昨年担当していたゲーム開発プロジェクトでは、まさにエンジニアがミリミリレイアウト調整をやりビルドに時間がかかって開発工数を圧迫してました。。。。入れておけばよかったと後悔してます。。。


何はともあれ環境構築


Cocos2d-xのインストール

当たり前ですがCocos2d-xをインストールし、Cocos Studioで組んだレイアウトを組み込むCocos2d-xのプロジェクトを作っておきます

参考にしたサイト

[Cocos2d-x ver3.4] MacOSXインストール手順


Cocos Studioのインストール

Cocos(+CocosStudio)をインストールし、プロジェクトを作成します

今回はCocos2d-xの作業とCocosStudioの作業を両方自分がやるので、CocosStudioのプロジェクトファイルをCocos2d-xのプロジェクトファイル内に移しておきます

こうしておくとCocosStudioでPublishしたcsbファイルをすぐCocos2d-x側でビルド組み込みできるので少し楽、というだけです(本来は作業者が分かれると思うので、ここを一緒にする必要はないと思います)

参考にしたサイト:

2015/11現在のCocos2d-X(とCocosStudio)インストール方法最新版

[Cocos2d-x] Cocos Studio2 を使ってみる (基本編)

とりあえず、作業環境が準備できました


まずはレイアウトを作成してみよう


作業手順


  • Nodeの作成

  • 画像の追加とNodeへ配置

  • シミュレーターで確認

  • Publishしてcsbファイルをビルド


Nodeの作成

Resourcesのプロジェクト下にNewFileでNodeを追加します

cocosstudio_newfile.png

NewFileダイアログでNodeを選択して、File Nameを設定してNewボタンを押下します

cocosstudio_nodenew.png

Nodeが追加されました(何もないように見えるがプロジェクトの下にNodeが追加されてます)

cocosstudio_startnode.png


画像の追加とNodeへ配置

レイアウトで使う画像をCocos StudioのResourcesにドラッグ&ドロップで追加します

cocosstudio_imgadd.png

追加した画像をステージにドラッグ&ドロップで追加し、レイアウトを作成します

cocosstudio_imgdrag.png


シミュレーターで確認

ヘッダメニューにある矢印を押してシミュレーターで表示してみます

cocosstudio_previewheader.png

cocosstudio_preview.png

この時点でプロジェクトファイル内のcocosstudioフォルダにcsdファイルが生成されています

cocosstudio_csd.png

試しに定義ファイル(csdファイル)の中身を見るとXMLでこんな感じで定義されてます


sample.csd

<GameFile>

<PropertyGroup Name="startNode" Type="Node" ID="8b6553db-9070-4403-ac8f-61aef56b56b0" Version="2.3.3.0" />
<Content ctype="GameProjectContent">
<Content>
<Animation Duration="0" Speed="1.0000" />
<ObjectData Name="Node" Tag="8" ctype="GameNodeObjectData" />
</Content>
</Content>
</GameFile>


Publishしてcsbファイルをビルド

csdファイルをそのままCocos2d-xに組み込むこともできるようですが、今回はビルドしたcsbファイルの方を組み込んでみます

ヘッダメニューよりPublishを選択します

cocosstudio_publish.png

設定ダイアログが表示されるので、Publish Resourceを選択してPublishします(これでcsbファイルがビルドされます)

cocosstudio_publishdialog.png


作成したバイナリをCocos2d-xでロードして画面に表示


作成手順


  • TOPページ用レイアウトを作成してPublish

  • Topページ用のTopSceneクラスを作成

  • csbファイルを読み込んでノード追加

  • シミュレーターで確認


TOPページ用レイアウトを作成してPublish

まずTopページ用のレイアウトにするためにCocos Studioでタイトルロゴとスタートボタンを追加してPublishし直します

スタートボタンは画像ではなくボタンオブジェクトで追加します

cocosstudio_buttonadd.png

ボタンオブジェクトのFeature - Backgroundプロパティにボタン画像をドラッグ&ドロップします。また、Nameプロパティは後々Cocos2d-x側でボタンタップ時の制御を追加するときにこのNameを元にオブジェクトを特定しますので、意味のある名前をつけます。今回は「btn_start」としました

cocosstudio_buttonimg.png

プレビューするとこんな感じです

cocosstudio_toppage.png

Publishしてcsbファイルを作成します

これでCocos Studioのレイアウト作成は完了しました


Topページ用のTopSceneクラスを作成

Cocos2d-xでTopページ用のTopSceneクラスを作成します

まずヘッダファイルに以下の2つをincludeします


TopScene.hpp

// ...省略

#include "cocostudio/CocoStudio.h"
#include "cocosGUI.h"

// ...省略


あとは通常のSceneクラスの要領で作成します

自分はこんな感じにしてみました


TopScene.hpp

#include "cocos2d.h"

#include "cocostudio/CocoStudio.h"
#include "cocosGUI.h"

class TopScene : public cocos2d::Layer
{
public:
static cocos2d::Scene* createScene();
virtual bool init();
CREATE_FUNC(TopScene);
static void pushBtnCallback(Ref *object);
};


csbファイルを読み込んでノード追加

csbファイルの読み込みはcppファイルのinitメソッド内にこんな感じで組み込みます

CSLoader::getInstance()->createNodeメソッドでcsbファイルをロードし、表示位置を調整した上でthis->addChildメソッドで追加してます


TopScene.cpp

bool TopScene::init()

{
// ...省略

// Directorを取り出す
auto director = Director::getInstance();
// 画面サイズを取り出す
auto size = director->getWinSize();
// TopSceneのCocosStudioバイナリを読み込む
auto node = CSLoader::getInstance()->createNode("startNode.csb");
// スプライトの表示位置を設定する
node->setPosition(Vec2(size.width / 2.0, size.height / 2.0));
this->addChild(node);

// ...省略

return true;
}


Cocos2d-xのシミュレーターで見てみます

cocos2dx_Toppage.png

。。。なんとなく収まってない。。。

今回は解像度を手持ちの画像サイズの関係で640x960で試しているんですが、Cocos Studioではうまく表示していたのがCocos2d-xに組み込むとうまくいってないですね。すみません

実はcsbファイルを組み込む過程で、Appdelegateの中で使っているsetContentScaleFactorメソッドがうまく動かずレイアウトを壊してしまうので、一旦以下のようにコメントアウトしてます。。。


AppDelegate.cpp

    // ...省略

// Set the design resolution
glview->setDesignResolutionSize(mediumResolutionSize.width, mediumResolutionSize.height, ResolutionPolicy::NO_BORDER);

/* Cocos Studioのレイアウトを読み込む場合うまく表示できないのでコメントアウト
Size frameSize = glview->getFrameSize();
// if the frame's height is larger than the height of medium size.
if (frameSize.height > mediumResolutionSize.height)
{
director->setContentScaleFactor(MIN(largeResolutionSize.height/designResolutionSize.height, largeResolutionSize.width/designResolutionSize.width));
}
// if the frame's height is larger than the height of small size.
else if (frameSize.height > smallResolutionSize.height)
{
director->setContentScaleFactor(MIN(mediumResolutionSize.height/designResolutionSize.height, mediumResolutionSize.width/designResolutionSize.width));
}
// if the frame's height is smaller than the height of medium size.
else
{
director->setContentScaleFactor(MIN(smallResolutionSize.height/designResolutionSize.height, smallResolutionSize.width/designResolutionSize.width));
}
*/

register_all_packages();
// ...省略


これ何ででしょうね。。。このあたりもう少し色々調べる必要があるのですが、一旦先に行ってしまいます


ボタン処理を組み込む


作業手順

- 遷移先ページのレイアウト作成

- 遷移先ページのクラスを作成

- Topページのスタートボタンにタッチイベントと遷移処理を追加


遷移先ページのレイアウト作成

まず遷移先であるPlayerページのレイアウトをCocos Studioで作成します

一旦はただの背景しかないこんなページを作成してPublishします

cocosstudio_playerpage.png


遷移先ページのクラスを作成

Cocos2d-xでPlayerSceneクラスを作成します

先ほどのシンプルなページを表示するだけなので、普通にSceneクラスを作成して、TopSceneと同じように以下の記述を追加します


PlayerScene.hpp

// ...省略

#include "cocostudio/CocoStudio.h"
#include "cocosGUI.h"

// ...省略



PlayerScene.cpp

bool PlayerScene::init()

{
// ...省略

// Directorを取り出す
auto director = Director::getInstance();
// 画面サイズを取り出す
auto size = director->getWinSize();
// PlayerSceneのCocosStudioバイナリを読み込む
auto node = CSLoader::getInstance()->createNode("playerNode.csb");
// スプライトの表示位置を設定する
node->setPosition(Vec2(size.width / 2.0, size.height / 2.0));
this->addChild(node);

// ...省略

return true;
}



Topページのスタートボタンにタッチイベントと遷移処理を追加

TopページのスタートボタンにaddTouchEventListenerメソッドを使ってタッチイベントを追加するんですが、Cocos StudioでNameプロパティに設定したボタンオブジェクトの名前キーに、getChildByNameメソッドを使ってスタートボタンを特定します

タッチイベント発火時には、今回追加したPlaerSceneへ遷移するように処理を追加してます


PlayerScene.cpp

bool TopScene::init()

{
// ...省略
// ボタンノードを取得
auto startBtn = node->getChildByName<ui::Button*>("bt_start");
// タッチイベント追加
startBtn->addTouchEventListener([this](Ref* sender, ui::Widget::TouchEventType type) {
// タッチが終わった後に実行
if (type == ui::Widget::TouchEventType::ENDED || type == ui::Widget::TouchEventType::CANCELED) {
TopScene::pushBtnCallback(sender);
}
});
return true;
}

void TopScene::pushBtnCallback(Ref *object){

CCLOG("スタートボタンが押された");

auto scene = PlayerScene::createScene();

// 0.5秒かけてホワイトアウトしてTopSceneに遷移させる
TransitionFade* fade = TransitionFade::create(0.5f, scene, Color3B::WHITE);

//Splashを破棄してPlaeyrSceneに遷移する
Director::getInstance()->replaceScene(fade);
}


あらかじめボタンのNameプロパティの値を決めておくことで、Cocos Studioでのレイアウト制作作業とCocos2d-xのエンジニアコーディング作業を並行で進めていくことができますので、そのあたりCocos Studioを使う上でのメリットになっている気がします


スプライトシートで画像を切り替える


作業手順


  • スプライトシートの作成

  • スプライトシートの組み込みと画像の切り替え


スプライトシートの作成

Cocos Studioで複数の画像を合成したスプライトシートを作成できるようなので使ってみます

まずは複数画像を放り込むフォルダを作成します

cocosstudio_newfolder.png

合成する画像を全て放り込みます

cocosstudio_importimg.png

スプライトシートを作成します

cocosstudio_plistdialog.png

合成する画像をドラッグ&ドロップでスプライトシートに追加します

cocosstudio_plistimg.png

Publishするとビルドされ、plistファイルが作成されます

cocosstudio_plist.png

ちなみにplistファイルの出力内容はこんな感じで、keyに出力されている「parts/fruit0.png」を使って画像を取り出すことになります


FruitsPlist.plist

<?xml version="1.0" encoding="utf-8"?>

<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>frames</key>
<dict>
<key>parts/fruit0.png</key>
<dict>
<key>frame</key>
<string>{{0,0},{32,32}}</string>
<key>offset</key>
<string>{0,0}</string>
<key>rotated</key>
<false />
<key>sourceSize</key>
<string>{32,32}</string>
</dict>
<key>parts/fruit1.png</key>
<dict>
<key>frame</key>
<string>{{0,32},{32,32}}</string>
<key>offset</key>
<string>{0,0}</string>
<key>rotated</key>
<false />
<key>sourceSize</key>
<string>{32,32}</string>
</dict>
<!-- ...省略 -->
</dict>
</plist>


スプライトシートの組み込みと画像の切り替え

組み込み方は、まずSceneクラスのinitメソッドでplistの追加を行います


PlayerScene.cpp

bool PlayerScene::init()

{
// ...省略

SpriteFrameCache::getInstance()->addSpriteFramesWithFile("parts/FruitsPlist.plist");

// ...省略
return true;
}


そして画像を取り出したいところでcreateWithSpriteFrameNameメソッドを使って取り出します


PlayerScene.cpp

    // ...省略

auto fruit = Sprite::createWithSpriteFrameName(filename);

// ...省略


シミュレーターで実行するとこんな感じです

フルーツ画像をランダムに取り出して下に落としてます

cocos2dx_plist.png

今回使った素材は自分が最初に購入したCocos2d-xの書籍の付属素材です。詳細はこちらをご確認ください


最後に

ほとんどスマートフォンアプリの開発経験のない自分としては、この程度のお試しをやるだけでかなり時間がかかってしまいました。。。でも自分のやったことのない技術に触るのはとても楽しいですねー。今回はCocos Studioとはどんなもんぞ、という感じでほんの触りだけやってみましたが、サイバードは今後Cocos2d-xでいけてるゲームを作るにあたって、このUIエディターを使いこなせるかどうかは開発効率とプロセス改善にかなりの差が出ると認識してまして、今後も色々取り組んでいきたいです、ハイ。

CYBIRDエンジニア Advent Calendar 2015 明日は前日の@yuichi_komatsuさんと同じくサイバードのデータ分析エンジニアである@cy-hiroshi-chibaさんが、Google Chartsについてのあれこれをお伝えするようですよ。お楽しみに〜