こんにちは、デザイナーの上松です。
ちょっと前から、ゲームの画像などの「リソース」を反映させる時に問題が起きていました。
Xcodeのキャッシュですぐに更新してくれなかったり、プログラマーさんを介さないと画像が反映できない点です。
今日紹介するアイディアを使えば、
・確実にリソースを反映できる
・ビルドしなくても(実行中でも)差し替え反映できる
・操作を覚えればグラフィッカーやデザイナが開発ソフトを入れなくても更新できる(!)
この3つのことができるようになります!
ファイルの読み込み先を変える
Cocos2d-xでは、ゲームのリソースを、CCFileUtilにあるSearchPathに設定されているフォルダからとってくるようになっています。
また、最初の状態はアプリ内のResourcesフォルダが設定されています。
このSearchPathは配列(ベクタ)になっており、先頭のフォルダから順に検索していき、なければエラーを返すような仕組みになっているようです。
ということで、このSearchPathの先頭に、任意のフォルダを指定すれば良さそうな感じがします。
データの書き込み先
読み込み先の変え方はわかりました。
つぎに、どこへデータを書き込むのかを考えましょう。
以下の3つのフォルダのどれかになります。
・Documentsフォルダ
・Library/Cacheフォルダ
・tmpフォルダ
基本的にデバッグ用ですのでどこでもOKです。
今回はgetWritablePathで簡単に取得できる、Documentsを使用しましょう。
データを書き込む
iOS端末の場合
iOS端末へ読み書きできるソフトを使うと便利です。
iFunBoxや、iExplorer等です。
有料版をお持ちでしたらiExplorerのマウント機能が私のおすすめです! 外付けディスクのようにFinderから書き込むことができます。
そうでなければ、iFunBoxをおすすめします。
どちらのソフトも、フォルダをドラッグアンドドロップして書き込むことができます。
iOSシミュレータの場合
あなたの現在のプロジェクトの、AppDelegate::applicationDidFinishLaunchingの中で、下のコードを動かして、パスを取得しましょう。
CCLOG("%s", CCFileUtils::sharedFileUtils()->getWritablePath().c_str());
私の場合は、こんな感じで出力されました。
/Users//Library/Application Support/iPhone Simulator/7.1-64/Applications//Documents/
このフォルダへFinderで移動して、書き込みます。
Macの中のフォルダなのでソフトを使わなくても書き込めます。
rsyncで同期をとるようにするとより便利です。
実際に読み出してみる
AppDelegate::applicationDidFinishLaunchingで、シーンが作られる前に、下のようなコードを書いておきます。
bool AppDelegate::applicationDidFinishLaunching() { // initialize director CCDirector *pDirector = CCDirector::sharedDirector(); pDirector->setOpenGLView(CCEGLView::sharedOpenGLView()); // turn on display FPS pDirector->setDisplayStats(true); // set FPS. the default value is 1.0/60 if you don't call this pDirector->setAnimationInterval(1.0 / 60); /* 即時プレビューができる仕込み */ // サーチパスの取得 vector paths = CCFileUtils::sharedFileUtils()->getSearchPaths(); // イテレータ生成 vector::iterator it = paths.begin(); // パスを挿入 paths.insert(it, CCFileUtils::sharedFileUtils()->getWritablePath() ); CCLOG("Path is here: %s", CCFileUtils::sharedFileUtils()->getWritablePath().c_str() ); // パスを反映 CCFileUtils::sharedFileUtils()->setSearchPaths( paths ); /* 仕込み終わり */ // create a scene. it's an autorelease object CCScene *pScene = HelloWorld::scene(); // run pDirector->runWithScene(pScene); return true; }
vectorとstringのincludeと、using namespace stdをお忘れなく!
この状態で起動します。
おなじみのHelloWorldシーンです。
ここで、以下のように色を変更したココスくんの画像を、Documents内に保存してみます。
アプリを終了して立ち上げ直すと・・・
反映されましたね!これで、ビルドやクリーンをしなくてもリソースだけ転送できるようになりました。
もっとリアルタイムにしたい
ここまででは、毎回起動し直さなければいけません。
動かしながら反映できればもっと便利そうです。
シーンに更新機能をつける
あくまでデバッグ機能ですので、シーンを再生成する方法で実現しましょう。
・画像などのキャッシュのクリア
・現在のシーンの新しいインスタンスを作る
・初期化する
・現在のシーンと差し替える
コードにするとこんな感じでしょうか。
電源ボタンのアクションで、アプリを終了する代わりに下記の処理を入れてみます。
//テクスチャ類のキャッシュ CCTextureCache::sharedTextureCache()->removeAllTextures(); //自身の新しいシーンを生成 CCScene* newScene = HelloWorld::scene(); //新しいシーンの設定する //newScene->hoge( init_dict ) //シーンを入れ替える CCDirector::sharedDirector()->replaceScene(CCTransitionFade::create(0.6f, newScene));
メニューボタンを押すとフェードアウト/インして、更新されるようになりました。
ボタン画像をエリザベスにしても問題なく動きます。
また、調整も、直接Photoshopから書き込みできるためさくさくです!
(シミュレーターやマウントした場合です)
ただ、この機能をすべてのシーンにつけるのは大変そうです。
なので、よく使うメニューや、辿り着きにくいシーンなどに限定して実装したり、最初からデバッグ用シーンを作ってしまう方が良いのではと思います。
まとめ
これで、SearchPathに書き込みできるフォルダを追加して、ビルドなしでリソース反映ができるようになりました。
CCBIファイルを使った画面作りや、Luaを使ってプログラムを書いている場合は、もっと相性が良さそうですね。