Cordovaで、iOS実機でデバッグする際にconsole.logをXcodeのコンソールに出力したい場合、以下のプラグインが必要。
cordova plugin add cordova-plugin-console
Cordovaで、iOS実機でデバッグする際にconsole.logをXcodeのコンソールに出力したい場合、以下のプラグインが必要。
cordova plugin add cordova-plugin-console
cordova のiOS用の設定である”BackupWebStorage”を”local”などに変更したい場合、プロジェクトディレクトリの下にある platforms/ios/cordova/defaults.xml の中の
<preference name=”BackupWebStorage” value=”cloud” />
を変更すればいい。
cocos2d-xの2.2.2での話。
cocos2d-xにpushSceneがあることに、つい先ほど気付いた。
シーンを完全に置き換えるreplaceSceneがあることは当然知っていたのだけど、前のシーンを残した状態で新たなシーンに遷移するpushSceneがあることを見落としていた。
(普通に考えれば、そりゃあるよね)
たとえば、ゲームのプレイ画面からメニュー画面を開くとき。
pushSceneでメニュー画面に遷移して、popSceneでプレイ画面に戻ってこられるので、なかなか便利だ。
中でも何が一番便利かといえば、CCTransitionXXを使って簡単に遷移アニメーション効果を付けられるところだろう。
ただし。
pushSceneにはCCTransitionXXをセットできるのだけど、不思議な事にpopSceneにはそれができない。
せっかく遷移アニメーションで気持ちよくメニュー画面を開いても、閉じるときに何もなくただ切り替わるだけでは違和感ありありで使えない。
そこで調べてみたところ、CCDirectionに手を加える事でpopSceneにCCTransitionXXをセットすることができた。
本当はCCDirectionなどに手を加えたくはないのだけど、他に方法はなさそうなのでしょうがない。
CCDirection.cppに以下の2つのメソッドを追加する。
(当然ヘッダーファイルの書き換えも必要)
// ひとつ前(戻り先)のCCSceneを返す CCScene *CCDirector::previousScene(void) { unsigned int c = m_pobScenesStack->count(); if (c < = 1) return NULL; return (CCScene*)m_pobScenesStack->objectAtIndex(c - 2); } // トランジションを指定してpopSceneする void CCDirector::popSceneWithTransition(CCScene *trans) { CCAssert(m_pRunningScene != NULL, "running scene should not null"); m_pobScenesStack->removeLastObject(); unsigned int c = m_pobScenesStack->count(); if (c == 0) { end(); } else { m_bSendCleanupToScene = true; m_pNextScene = trans; } }
こんなふうに使います。
CCDirector *director = CCDirector::sharedDirector(); // 戻り先のシーンを取得。 CCScene *scene = director->previousScene(); // トランジションを作成。 CCTransitionScene* transition = CCTransitionSlideInL::create(0.5f, scene); // トランジションを指定してpopSceneする director->popSceneWithTransition(transition);
test
CCScene *CCDirector::previousScene(void) { unsigned int c = m_pobScenesStack->count(); if (c <= 1) return NULL; return (CCScene*)m_pobScenesStack->objectAtIndex(c - 2); } void CCDirector::popSceneWithTransition(CCScene *trans) { CCAssert(m_pRunningScene != NULL, "running scene should not null"); m_pobScenesStack->removeLastObject(); unsigned int c = m_pobScenesStack->count(); if (c == 0) { end(); } else { m_bSendCleanupToScene = true; m_pNextScene = trans; // (CCScene*)m_pobScenesStack->objectAtIndex(c - 1); } }
CCScene *CCDirector::previousScene(void) { unsigned int c = m_pobScenesStack->count(); if (c <= 1) return NULL; return (CCScene*)m_pobScenesStack->objectAtIndex(c - 2); } void CCDirector::popSceneWithTransition(CCScene *trans) { CCAssert(m_pRunningScene != NULL, "running scene should not null"); m_pobScenesStack->removeLastObject(); unsigned int c = m_pobScenesStack->count(); if (c == 0) { end(); } else { m_bSendCleanupToScene = true; m_pNextScene = trans; // (CCScene*)m_pobScenesStack->objectAtIndex(c - 1); } }
CCScene *CCDirector::previousScene(void) { unsigned int c = m_pobScenesStack->count(); if (c <= 1) return NULL; return (CCScene*)m_pobScenesStack->objectAtIndex(c - 2); } void CCDirector::popSceneWithTransition(CCScene *trans) { CCAssert(m_pRunningScene != NULL, "running scene should not null"); m_pobScenesStack->removeLastObject(); unsigned int c = m_pobScenesStack->count(); if (c == 0) { end(); } else { m_bSendCleanupToScene = true; m_pNextScene = trans; // (CCScene*)m_pobScenesStack->objectAtIndex(c - 1); } }
CCScene *CCDirector::previousScene(void) { unsigned int c = m_pobScenesStack->count(); if (c <= 1) return NULL; return (CCScene*)m_pobScenesStack->objectAtIndex(c - 2); } void CCDirector::popSceneWithTransition(CCScene *trans) { CCAssert(m_pRunningScene != NULL, "running scene should not null"); m_pobScenesStack->removeLastObject(); unsigned int c = m_pobScenesStack->count(); if (c == 0) { end(); } else { m_bSendCleanupToScene = true; m_pNextScene = trans; // (CCScene*)m_pobScenesStack->objectAtIndex(c - 1); } }
Particle Editor for Cocos2d and V-Playという、Cocos2dで使えるパーティクルエディターを知ったので、さっそく使ってみた。
ちなみに、試したのはMac用。
まずダウンロード先だけど、リンク先のページの本文中にある「Free to download」がそれ。
ページ上部にあるメニューの中の「download」だと、V-Playというゲームエンジンのダウンロード先になるので注意。
起動するとこんな画面。
炎のパーティクルがひとつ表示されている状態だ。
左右のタブをクリックするとメニューが開く。
まずは左のメニューを開いてみる。
“Main Menu”の項目がずらりとならぶ。
スクロールはスマホのタッチディスプレイの要領で行う。
項目を上から順にざっと説明すると、
“Add XXX” で、別のところで選択したパーティクルXXXを画面上に追加する。
その上にある”CreationCount” が追加する数。
“Save as”で編集したパーティクルを保存。
保存場所は、Documents > Particle Editor for Cocos2d and V-Play > particles。
“Respawn Particles”で、パーティクルを初めから再生し直すんじゃないかと思う、たぶん。
“Remove All”,”Remove First”,”Remove Last”で、追加したパーティクルを削除。
“Save to .plist”で、plist形式で保存。
ちなみに、先ほどの”Save as”だとJSON形式で保存される。
“Send Particle .json”,”Send Particle .plist”は、”Save as”,”Save to .plist”の内容をメールで送信するためのものだと思う。
モバイルアプリ版もあるようなので、それ用の機能だろう。
右向き三角をクリックして、”Particles”メニューに切り替える。
ここに用意されたパーティクルが並ぶ。
“Main Menu”の”Save as”で保存したパーティクルもここに並ぶ。
リストからパーティクルを選択し”Main Menu”に戻り、”Add XXX”で追加する。
再び三角ボタンをクリックして”Background”メニューに切り替える。
“Red”,”Green”,”Blue”のスライダーで画面の背景色を変更できる。
“Entity Base Visible”をtrueにすると、画面上のパーティクルの基準点にうっすらと四角形が表示される。
ちなみに、画面上のパーティクルは、この基準点をドラッグすることで好きな場所に移動できる。
こちらのメニューには、パーティクルの各種パラメータの設定項目がずらりと並ぶので、説明は省略。
Particle Editor for Cocos2d and V-Play独自の操作方法にだけ触れておくと、変更したパラメータは、スライダーをクリックするとデフォルト値に戻せる、というか、戻ってしまう。
また、画面上に複数のパーティクルを置いているとき、編集対象となるパーティクルを切り替えるには、右メニューの一番上にあるパーティクルの名前のあたりをクリックする。
すると、パーティクルの名前の一覧がオーバーレイで表示されるので、そこで選択する。
この一覧が半透明で、下の表示と被って見づらいので気をつけよう。
あと注意点としては、plistを書き出す際に、使用しているテクスチャ(パーティクルの画像)のデータは出力されない。
plist中の”textureFileName”項目にファイル名が記述されるだけなので、そのままのテクスチャ画像を使用したければ、自力で画像ファイルを漁ってこなければならない。
アプリ本体をcontrol+クリックして「パッケージの内容を表示」し、Contents > Resources > qml > particlesに画像ファイルがある。
ちなみに、ここに画像ファイルを置けば、自前のテクスチャ画像をParticle Editor for Cocos2d and V-Playに追加できるのでは?と思ったけど、ダメだった。
何か自前のテクスチャ画像を追加する方法があるのかもしれないけど、今のところ分からない。
以上。
使い勝手に少し癖があったり、まだまだ改良の余地があるのではと思うけれど、無料でこれだけ使えれば十分ありだと思う。
今後大いに使って行きたい。
cocos2d-xの標準JSONパーサーといえば spine Jsonだけど、spine Jsonでは、数値データはすべてfloatで扱われる。
現在製作中のアプリではデータをJSON形式で保存しているのだけど、日時のデータをJSON形式でファイルに保存し、次に読み込むと、どうも日時がずれていることに気がついた。
日時のデータは time_t 形式の値で、JSON上ではintとして扱っている。
ところが、一旦保存して次にこれを読み込む際には、spine Jsonはこの値をfloat値としてパースする。
調べてみたところ、このとき僅かではあるが、JSON文字列に記述された値とfloatにパースされた値との間に誤差が生じていることが分かった。
float計算には誤差がつきものと言うが、どうやら、大きな整数値をfloat計算でパースしようとすると、この誤差が無視できなくなってしまうようだ。
そこで、整数値は整数値としてパースするように spine Json を修正することにした。
まずは、spineのJson.hのstruct Jsonに、値が整数値かfloat値かを示すフラグ変数を新たに追加する。
/* The Json structure: */ typedef struct Json { struct Json* next; struct Json* prev; struct Json* child; int type; const char* valuestring; int valueint; float valuefloat; bool isInteger; // 整数値かfloat値かを判別するためのフラグ const char* name; } Json;
整数値かfloat値かを示すフラグ変数を導入する代わりに、 Json_NumberをJson_IntとJson_Floatに分けるやりかたもあるかと思うが、このやり方のほうが他のコードへの影響が小さくて良いのではないかと思う。
次に、Json.cppの static const char* parse_number (Json *item, const char* num) を次のように修正する。
/* Parse the input text to generate a number, and populate the result into item. */ static const char* parse_number (Json *item, const char* num) { // 途中の計算はすべてintで行う。 int n = 0, sign = 1, scale = 0, subscale = 0, signsubscale = 1; if (*num == '-') sign = -1, num++; if (*num == '0') num++; if (*num >= '1' && *num <= '9') do n = (n * 10) + (*num++ - '0'); while (*num >= '0' && *num <= '9'); if (*num == '.' && num[1] >= '0' && num[1] <= '9') { num++; do n = (n * 10) + (*num++ - '0'), scale--; while (*num >= '0' && *num <= '9'); } if (*num == 'e' || *num == 'E') { num++; if (*num == '+') num++; else if (*num == '-') signsubscale = -1, num++; while (*num >= '0' && *num <= '9') subscale = (subscale * 10) + (*num++ - '0'); } int s = scale + subscale * signsubscale; if (s == 0) { // 整数 n = sign * n; item->valuefloat = (float)n; item->valueint = n; item->isInteger = true; } else if (s > 0) { // 10のs乗の整数 n = sign * n * (int)pow(10.0, s); item->valuefloat = (float)n; item->valueint = n; item->isInteger = true; } else { // sが負数なので、小数 float n2 = (float)sign * (float)n * (float)pow(10.0f, s); item->valuefloat = n2; item->valueint = (int)n2; item->isInteger = false; } item->type = Json_Number; return num; }
これであとは、たとえばこんなふうに使えばいい。
CCObject *CCJson::parseValue(Json *pJsonValue) { if (pJsonValue->type == Json_Number) { if (pJsonValue->isInteger) { // 整数値 return CCInteger::create(pJsonValue->valueint); } else { // float値 return CCFloat::create(pJsonValue->valuefloat); } } }