ラベル cocos2d-x の投稿を表示しています。 すべての投稿を表示
ラベル cocos2d-x の投稿を表示しています。 すべての投稿を表示

2017年9月26日火曜日

Xcode8のままiOS11ビルドをする

どうも俺です。


iOS11がリリースされ、それに合わせてXcode v9もリリースされました。
Xcodeをバージョンアップするためには、
先にMacOSをバージョンアップする必要があって...いつもながら超面倒です。

Xcode8のままだとiOS11用にビルドできない...とお思いのみなさん、
裏技を使ってそのままiOS11ビルドできます。

※動作保証はできませんので、自己責任で行って下さい。


(1) Xcode 9をダウンロードする
https://developer.apple.com/download/more/
からXcode 9をダウンロードし解凍します。
結構時間かかります。

(2) Xcode 9.appを適当なディレクトリへおく
/Application/Xcode-9.app などへ移動させましょう。

(3) Xcode 8を適当な名前にリネームしておく。
仮に、Xcode-8.app としておきましょう。

(4) Xcode 8.appにXcode 9.app内にあるiOS11ディスクイメージのシンボリックを貼る

$ sudo ln -s /Applications/Xcode-9.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport/11.0\ \(15A5278f\) /Applications/Xcode-8.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport/11.0

(5) Xcode 8.appを再起動
再起動したら準備OK。iOS11端末をつなげてビルドできます。




ここに答えが。
Use Xcode 8 with iOS 11 | stack overflow



以上でぇぇぇぇす。

2017年8月8日火曜日

linker command failed with exit code 1が出た時の解決方法案

どうも、俺です。

Xcodeで開発してて目にすると1時間はその解決に費やしてしまうこともある地獄のエラー文言。
そう、それが
linker command failed with exit code 1


※Xcode 8.3.3

今日はこのエラーが出た時「これやったら直った」というあらゆる手段をお伝えします。


■プロビジョニングプロファイルは正しく設定されているか

人により設定方法は様々ですが、僕の場合、
・General>SigningにあるAutomatically manage signingのチェックをはずす

・Build Settings内、
 ProvisioningProfile (Deprecated)とProvisioning Profileの2箇所に適切なプロビジョニングプロファイルを設定。
 Code Signing Identityに正しい証明書を設定。
 最後にDevelopment Teamにチーム名を設定。

としています。
このミスの際は、ちゃんと「プロビジョニングプロファイル間違えているよ」というエラーが出ることが多い...。


■Enable Bitcodeの設定を間違えていないか

Build Settings>Build Options内にあるEnable Bitcodeが「Yes」になっているとアカン場合がある。
組み込んだフレームワークがbitcodeとやらに対応していないかもしれないので、速攻「No」に設定し直す。




■存在しないリソース(画像etc)を取り入れようとしていないか

Build Phases>Copy Bundle Resources内に存在しないリソースがないか要チェック。
無いものが含まれている場合は削除します。



■Deployment Targetを間違えていないか

General>Deployment InfoにあるDeployment Targetに無茶な値を入れていないか。
古すぎるターゲットなどに設定している場合は、よく考えて適切な値にします。



■Info.plistの設定Target Membershipは大丈夫か

Info.plistを選択してTarget Membershipにチェックが入っているとアウト。
チェックを外します。



■Xcodeを再起動しよう

この方法を使うと90%の確率でビルドが成功します。
試してみる価値あり。



■Mac本体ごと再起動しよう

この方法を使うと50%の確率でビルドが成功します。
試してみる価値あり。




上記以外でこのエラーの対処方法があれば教えてください。


※※※2017.08.18追記
このエラーが出た時に詳細ログが見れないのでモヤモヤしてたのですが、ログを見る方法が分かりました!
command+8 !!
LogNavigatorというやつらしいです!
これで具体的にエラー内容確認できます!


以上でぇぇぇぇす。

2016年6月8日水曜日

iOS/Androidアプリ「究極リバーシ」 リリースしました

どうも、俺です。 cocos2d-x v3.10で開発したアプリ「究極リバーシ」をリリースしました。
・iOS
https://itunes.apple.com/jp/app/ultimate-reversi/id1114493417?mt=8 
・Android
https://play.google.com/store/apps/details?id=jp.marge.android.reversi

最近よく耳にする、人工知能(AI)と対戦するリバーシアプリです。



はじめてのcocos2d v3系でしたが、
殆どの部分でv2系と同じような実装ができたので、それほど大きく戸惑う事はありませんでした。
一番困ったのは、CCArrayとCCDictionaryがなくなったことでしょうか。
Vectorクラス or Mapクラスを使うかstd::vectorを使うか、、、
結局std::vectorを一番使いました。

また、今回リバーシAIを実装するということで、
いろんなサイトからリバーシのAIについて勉強しまくりました。
ゲーム機探索や盤面の評価方法、MinMax/AlphaBeta/NegaScout法など、
ゲームのAIを実装する上で必要なノウハウを色々学べました。

あと、6/1からiOS審査でIPv6-only Networkで動作出来ることが必須になったということで、
急遽cocos2d-x v3.11.1でもビルドして試してみたのですが、
なぜかAndroid v4系で、
Jniの呼び出しでクラッシュが発生してしまい、諦めました。

一応、対応方法はここを参考に。



以上でぇぇぇす。

2016年6月7日火曜日

[cocos2d-x] OpenGL error 0x0506が出てフリーズ

どうも、俺です。
cocos2d-x(v3.10)で開発していて、
動画広告(今回はAppLovin)を表示し終わってアプリに戻ってきた時に、

2016-06-07 19:01:38.787 XXXXX-mobile[9739:3517670] cocos2d: surface size: 640x1136
2016-06-07 19:02:15.736 XXXXX-mobile[9739:3517670] failed to call context
2016-06-07 19:02:15.737 XXXXX-mobile[9739:3517670] cocos2d: surface size: 0x0
2016-06-07 19:02:15.737 XXXXX-mobile[9739:3517670] Failed to make complete framebuffer object 0x8CD6
OpenGL error 0x0506 in /Users/XXXXX_name/Documents/cocos2d-x/v3.10/XXXXX-mobile/cocos2d/cocos/renderer/CCFrameBuffer.cpp applyFBO 445

FrameBuffer Status Error 36054
OpenGL error 0x0506 in /Users/XXXXX_name/Documents/cocos2d-x/v3.10/XXXXX-mobile/cocos2d/cocos/renderer/CCFrameBuffer.cpp applyFBO 445

FrameBuffer Status Error 36054
FrameBuffer Status Error 36054
OpenGL error 0x0506 in /Users/XXXXX_name/Documents/cocos2d-x/v3.10/XXXXX-mobile/cocos2d/cocos/renderer/CCRenderer.cpp saveRenderState 161

OpenGL error 0x0506 in /Users/XXXXX_name/Documents/cocos2d-x/v3.10/XXXXX-mobile/cocos2d/cocos/renderer/CCTextureAtlas.cpp drawNumberOfQuads 691

OpenGL error 0x0506 in /Users/XXXXX_name/Documents/cocos2d-x/v3.10/XXXXX-mobile/cocos2d/cocos/renderer/CCRenderer.cpp restoreRenderState 192

FrameBuffer Status Error 36054
OpenGL error 0x0506 in -[CCEAGLView swapBuffers] 324
OpenGL error 0x0506 in /Users/XXXXX_name/Documents/cocos2d-x/v3.10/XXXXX-mobile/cocos2d/cocos/renderer/CCFrameBuffer.cpp applyFBO 445

FrameBuffer Status Error 36054
OpenGL error 0x0506 in /Users/XXXXX_name/Documents/cocos2d-x/v3.10/XXXXX-mobile/cocos2d/cocos/renderer/CCFrameBuffer.cpp applyFBO 445

FrameBuffer Status Error 36054
FrameBuffer Status Error 36054
OpenGL error 0x0506 in /Users/XXXXX_name/Documents/cocos2d-x/v3.10/XXXXX-mobile/cocos2d/cocos/renderer/CCRenderer.cpp saveRenderState 161

OpenGL error 0x0506 in /Users/XXXXX_name/Documents/cocos2d-x/v3.10/XXXXX-mobile/cocos2d/cocos/renderer/CCTextureAtlas.cpp drawNumberOfQuads 691

OpenGL error 0x0506 in /Users/XXXXX_name/Documents/cocos2d-x/v3.10/XXXXX-mobile/cocos2d/cocos/renderer/CCRenderer.cpp restoreRenderState 192
こんなエラーが出まくって何もできなくなってしまった場合。

RootViewController.mmに以下を追記しましょう。

-(void)viewWillAppear:(BOOL)animated
{
    cocos2d::Director::getInstance()->resume();
    cocos2d::Director::getInstance()->startAnimation();
}

- (void)viewWillDisappear:(BOOL)animated
{
    cocos2d::Director::getInstance()->pause();
    cocos2d::Director::getInstance()->stopAnimation();
}

Quiteを参照。

以上でぇぇぇす。

2016年4月7日木曜日

[cocos2d-x] 'stop' is not a member of 'std'が出て困ったとき

どうも、俺です。
最近更新がマメです。

  • cocos2d-x v3.10
  • android-idk-r10e

を使用。

表題の件。
Android側をビルドしようとして、
'stoi' is not a member of 'std'
のエラーが出てしまい困っちんぐな場合の対応方法をメモ。

Android-NDKが std::stoi に対応していないのが原因だそうです。

        int number;
#if CC_TARGET_PLATFORM != CC_PLATFORM_ANDROID
        number = std::stoi("xxxxxxxxfugafuga");
#else
        number = atoi("xxxxxxxxfugafuga");
#endif

こんな感じOK。

以上でぇぇぇぇぇす。

2016年4月5日火曜日

cocos2d-xで画像がちらつく

どうも、俺です。

cocos2d-xで開発してて画像を連続で表示させた時などにチラついてしまう現象をなんとかしましょう。
Director::getInstance()->setDepthTest(false);
Director::getInstance()->setProjection(Director::Projection::_2D);

これを、AppDelegate::applicationDidFinishLaunching()に記述しておけばOKです。
TiledMapで画像がチラつく場合もこの対応でなんとかなるはずです。

以上でぇぇぇぇぇす。

2016年3月31日木曜日

cocos2d-x v3.10にアップデートして行ったEclipseの設定

どうも、俺です。
cocos2d-xをv2.2.6からv3.10にアップデートしたので、忘れないうちにメモ。

EclipseじゃなくてAndroidStudio使おうぜ、という指摘もあると思いますが、
EclipseでもAndroidStudioでも、両方でビルド出来るようにしたいのです。

まず、v2系で使っていたbuild_native.shはbuild_native.pyに置き換わり、スクリプトの中身を自分で変更しなくても良くなりました。
jni/Android.mkは適宜編集が必要です。


EclipseのRun実行時にbuild_nativeが自動で走らない。

そうです、なぜか自動でbiuld_nativeが走ってくれないので、その設定をば。
プロジェクトを選択し「Properties」>「Builders」を選択。
その中にあるCDT Builderにチェックが入っていないのでチェックします。



これに気づくまでは、手動で./build_native.pyを叩いていたのですが、
なぜかそうすると、libcocos2dx.jar(v3.10)とgoogle-play-services_lib.jarが毎回削除されてしまっていたので、
それぞれのプロジェクトも手動で「Build Project」する必要がありました。。


sh: cocos: command not found的なエラーが出る。

ビルド時にこのエラーが出て先にすすめません。
build_native実行時に呼ばれるcocosコマンドが見つからないそうなので、設定してやります。
先と同じく、プロジェクトを選択し「Properties」から「C/C++ Build」>「Environment」を選択します。
右側の「Add...」から
  • ANDROID_SDK_ROOT = 「ANDROID_SDKのパス」
  • ANT_ROOT = 「ANTのパス」
※例) /usr/local/Cellar/ant/1.9.5/libexec/bin
  • COCOS_CONSOLE_ROOT = 「cocosコマンドのあるパス」
※例) /PATH/TO/COCOS2DX/v3.10/tools/cocos2d-console/bin
  • PATH = 「${PATH}:${COCOS_CONSOLE_ROOT}:${ANDROID_SDK_ROOT}」
を設定します。


今のところ、このくらいです。
また出てくれば追記していきます。

2016年3月29日火曜日

C++で簡易マルチスレッド (C++98 / C++03)

どうも、俺です。

今日はC++を使ってのマルチスレッド実装をメモメモ。
※C++11より前のバージョンの話です。C++11ではもっと簡単に実装できます。


// mutexの定義。排他制御。
pthread_mutex_t mutex;

// Hogeクラスのコンストラクタ
HogeClass::HogeClass()
{
}

// マルチスレッド呼ばれる関数を定義
static void *hogeThreadFunc(void *param)
{
  pthread_mutex_lock(&mutex);

  // 何か重たい処理を行う。
  ....................

  pthread_mutex_unlock(&mutex);
  pthread_mutex_destroy(&mutex);

  return 0;
}

// スレッドを生成して呼び出すメソッド
static void HogeClass::hogeMethod()
{
  // スレッドID(識別子)
  pthread_t threadId;

  pthread_mutex_init(&mutex, NULL);

  // スレッド生成
  pthread_create(&threadId, NULL, hogeThreadFunc, NULL);
  pthread_detach(threadId);
}


こんな感じです。
複数のスレッドからいろんなインスタンスにアクセスするような場合は、
もっと慎重に排他制御を行う必要があると思います。


以上でぇぇぇぇぇす。

2016年3月17日木曜日

[cocos2d-x] C++で年月日時分秒を取得

どうも、俺です。

cocos2d-xを使っていて、C++で年月日を取得するtips。

time_t now = time(NULL);
struct tm *nowtime = localtime(&now);

・年 ... nowtime->tm_year+1900
・月 ... nowtime->tm_mon+1
・日 ... nowtime->tm_mday
・時 ... nowtime->tm_hour
・分 ... nowtime->tm_min
・秒 ... nowtime->tm_sec
で値が取れるので、

CCString *ymd = CCString::createWithFormat("%04d/%02d/%02d", nowtime->tm_year+1900, nowtime->tm_mon+1, nowtime->tm_mday);
int ymdInt = ymd->intValue();

とやると、
例えば20160317となる。

以上でぇぇぇぇぇす。

2015年12月22日火曜日

cocos2d-x CCRenderTextureでゲーム中のスクショを撮るときの注意点

どうも、俺です。

cocos2d-x (v2.2.6)でTwitter投稿用に画面のキャプチャを撮る処理を実装
したのですが、
キャプチャした時にCCParticleSystemでパーティクルを表示していると画面が真っ黒になってしまう問題に遭遇しました。
※すべてのパーティクルでなる訳ではありません。むしろ一部のパーティクルでのみ発生。
※iOSでのみ確認しましたが、恐らくAndroidでも同様のはず..。


赤いプレイヤーのうしろにある炎がパーティクルです。

キャプチャーの撮影処理は、
CCRenderTexture *AppDelegate::takePicture()
{
    CCSize size = CCDirector::sharedDirector()->getWinSize();
    CCRenderTexture *texture = CCRenderTexture::create((int)size.width,
                                                       (int)size.height,
                                                       kCCTexture2DPixelFormat_RGBA8888,
                                                       GL_DEPTH24_STENCIL8_OES);
    
    texture->setPosition(ccp(size.width * 0.5f, size.height * 0.5f));
    
    texture->begin();
    CCDirector::sharedDirector()->getRunningScene()->visit();
    texture->end();
    
    return texture;
}
のように処理しています。

この処理のままパーティクル描画ある画面をキャプチャすると、、

このように、パーティクル部分が黒くなってしまいます。

これは利用している炎のパーティクルのccBlendFunctionを変更することで対応できます。
今回の場合は、
    ccBlendFunc blend;
    blend.src = GL_ONE_MINUS_SRC_ALPHA;
    blend.dst = GL_ONE;
    _myFireParticle->setBlendFunc(blend);
    
    CC_SAFE_RELEASE_NULL(_screenShot);
    CCRenderTexture *screenShot = AppDelegate::takePicture();
    CC_SAFE_RETAIN(_screenShot);
    
    blend.src = GL_ONE_MINUS_SRC_ALPHA;
    blend.dst = GL_DST_ALPHA;
    _myFireParticle->setBlendFunc(blend);

このようにすることで対応できました。
※_myFireParticleは炎のCCParticleSystemインスタンス。

利用するccBlendFuncは、元のパーティクルが崩れない最も適したもので色々試してみてください。


以上でぇぇぇぇぇぇぇぇす。

2015年9月18日金曜日

cocos2d-x Spineのサンプルアニメーションが動かないのでランタイムを最新に更新する

どうも、俺です。

cocos2d-x v2.2.6でSpine v2.1.27(Essential)に梱包されているサンプルアニメーション(iOS版)が動かなかったので、
Spine-runtimeをマニュアル通り、最新verに更新したらcocos2d-xがエラーだらけになり、
四苦八苦しながら何とか動かせるようにまでにした時のメモ。


■Spineがexportする.atlasファイルが読み込めない問題
まず、自分で簡単なアニメーションを作成しSpineでエクスポートしたファイルを
cocos2d-xで動かそうとすると
、この問題にぶち当たります。

これは、出力された.atlasファイルを修正すると直ります。


上の画像にある
size: xxx, xxx
という1行を削除すればOKです。

または、このあと行うSpineのランタイムを更新すると直ります。


■Spineのランタイムを更新する問題
githubからランタイムをDLしてきます。
/spine-runtimes

更新に必要なファイルは
spine-c/以下 と
spine-cocos2dx/2/以下 のファイルだけです。
READMEにある通り、上のファイル群をcocos2d-xのextensions/フォルダ以下へコピーします。


元からあるextensions/spineフォルダは別名でバックアップしておきます。
githubからDLしたファイルすべてをまた
extensions/spineというフォルダに入れます。

READMEによるとこれで動くぜ、とのことです。


動きません。
なぜなら、Xcodeには前の古いファイルがまだ紐付けられているからです。


ここを正しくします。

やり方は色々ありますが、僕の場合は面倒なので
まずディレクトリーツリーからspine/をRemove Referencesしてから、

DLしてきたextensions/spineフォルダをXcodeへドラッグ&ドロップします。


ここでビルドしますが、まだまだ動きません。


No type named 'function' in namespace 'std'
といったエラーが出ます。

これは新しいSpine-runtime内のソースファイルの一部が
C++11の規格によって記述されているから。

cocos2d-x v3系であれば問題ない(?)のかもしれませんが、v2系ではだめです。
Xcode側でC++11を使えるようにします。



TARGETSのBuild Settings内にある「Apple LLVM 6.1 - Language - C++」という箇所の
・C++ Language Dialectを「C++11 [-std=c++11]」に
・C++ Standard Libraryを「libc++(LLVM C++ standard library with C++11 support)」
に変更します。

同様にcocos2d-xプロジェクト側のBuild Settingsも上に合わせます。



次にクラス名とメソッドを変更します。

// CCSkeletonAnimation *animation = CCSkeletonAnimation::createWithFile("test.json", "test.atlas");
spine::SkeletonAnimation *animation = spine::SkeletonAnimation::createWithFile("test.json", "test.atlas", 1.0f);

// animation->setAnimation("walk", true);
animation->setAnimation(0, "walk", true);

this->addChild(animation);

こうなります。

あとはプロジェクトを一旦Cleanしてからビルドすると動くと思います。

それでもまだエラーが出る場合は、
プロジェクト名>Build Phases>Compile Sources
に古いspine/以下のソースファイルが赤く表示されているかも知れません。
その場合はそれらを消してもう一度試してみてください。


※※注意※※
もし別のプロジェクトに手を付ける場合、
spine/フォルダや、C++11コンパイラオプションの変更などを元に戻して下さい。

もう、cocos2d-x v3系にしないとな。。。


以上でぇぇぇぇす。

2015年3月6日金曜日

cocos2d-xのメモリ対策について

どうも、俺@仕事中です。

昨年、cocos2d-x CCSprite(テクスチャ)の軽量化という記事を書きましたが、
今回も同じようにメモリ対策についてメモ。

■環境
・cocos2d-x 2.2.6
・Xcode 6.1.1

先に結論から言いますと、
CCSpriteFrameCacheやCCTextureCacheの使いすぎに注意、
または、メモリ不足に陥る前に正しくキャッシュデータを解放しましょう。
ということです。

CCSpriteFrameCacheCCTextureCacheは、
スプライトシートなどの画像データをメモリ上にキャッシュしてくれるため、
CCSpriteオブジェクトの生成時に高速&低負荷であることがメリットな反面、
メモリを消費します。(※1)

特にCCSpriteFrameCacheは大きなサイズは画像ファイル(スプライトシート)を
キャッシュすることがあるのでそのメモリ消費には要注意です。


例えば、
タイトル画面(TitleScene) → 遷移 → ゲーム画面(GameScene)
のような場合。

タイトル画面で表示するためのスプライトシートを読み込み、
またゲーム画面でもゲーム画面用のスプライトシートを読み込み、
といった処理を行うと、
両方の画面で読み込まれたスプライトシートはキャッシュされたままになります。




メモリが不足してくると、iOSでは
    AppController#applicationDidReceiveMemoryWarning:(UIApplication *)application; 
がコールされ、
cocos2d-xのバージョンによっては、
    CCDirector#purgeCachedData(void)
が呼ばれて、開発者が意図せず勝手にキャッシュデータが消去されます。

この状態だと、次にCCSpritFrameCacheからキャッシュデータを読み込もうとすると
エラーとなりアプリがクラッシュしてしまいます。


対応として、
1)CCDirector#purgeCachedData(void)を呼ばない。
2)不要になったタイミングでCCSpriteFrameCacheのキャッシュデータをクリアする。
が考えられます。

1)の方法は簡単&すぐに対応できますが、メモリ逼迫の原因は解消されません。
2)は、画面遷移の前などで
    CCSpriteFrameCache::sharedSpriteFrameCache()->removeSpriteFramesFromFile(const char *plist);
を呼べばOKです。

画面遷移の前というのは、
CCDirector#replaceScene(CCScene *pScene)
を呼ぶより前のタイミングです。
その該当するSceneのonExit()やデストラクタ内で、
    CCSpriteFrameCache::sharedSpriteFrameCache()->removeSpriteFramesFromFile(const char *plist);
を呼ぶと、
すでに遷移先のSceneオブジェクトが生成されてしまっているので、
タイミングとしてはちょっと遅いです。

※1) CCSpriteクラスのcreate(const char *fileName)メソッドや
initWithFile(const char *fileName)メソッドは、
内部でCCTextureCacheクラスのaddImage(const char *fileName)が呼ばれているため、
キャッシュされ、二回目以降の呼び出しは高速になる。


以上でぇぇぇぇぇす。

2015年1月26日月曜日

cocos2d-x Androidで"could not create track"エラー

どうも、俺@もう帰るです。

今日は、cocos2d-xでAndroid対応している時にハマった
AudioFlinger could not create track, status: -12

のエラーについてです。

・Xcode v6.1
・cocos2d-x v2.2.6
・eclipse Juno Service Release 2

現象ですが、
ゲーム開始時に、エンジンの効果音(.oggファイル)を
    int soundID = CocosDenshion::SimpleAudioEngine::sharedEngine()->playEffect("engineSound", true);
上述のようにループ再生させておき、
ポーズのタイミングなどでは効果音を停止させます。
    CocosDenshion::SimpleAudioEngine::sharedEngine()->stopEffect(soundID);

で、またゲーム再開させたときに、
    int soundID = CocosDenshion::SimpleAudioEngine::sharedEngine()->playEffect("engineSound", true);
最初は出ていたエンジン効果音が鳴らなくなる、
という症状になってしまいました。

その際、eclipseに出ていたエラーログは、
01-26 18:00:00.000: ERROR/AudioTrack AudioFlinger found not create track, status: -12
01-26 18:00:00.000: ERROR/AudioTrack Error creating AudioTrack
でした。

Webで調べたところ、
status: -12
というのは、
効果音をロードしてTrackを生成する時に必要となる
リソース(メモリ)不足が主な原因のようです。

しかし僕の場合は
それほどメモリを消費するような大きなサイズのサウンドファイルもない。

他にも調べてみて、以下の方法で解決できました。
anddev.org - SoundPool crashing with "could not create track"

該当のサウンドファイル(.ogg)のビットレートを
ステレオ320kbpsからモノラルの192kbsに下げました。

何kbpsにするのが適正なのかは定かではありませんが、
上記のようにしても音に大きな劣化などは感じられませんでした。
もし同じ症状で悩んでいる方がおられましたら、試してみてください。

以上でぇぇぇぇぇぇす。


2014年10月24日金曜日

[cocos2d-x] 謎の'string' file not foundエラー

どうも、俺@眠いです。

ある日突然、cocos2d-xでビルドを実行したときに
Lexical or Preprocessor Issue
'string' file not found

というエラーに出くわしました。

環境はMac OSX 10.9.5  +  Xcode v6.0.1 + cocos2d-x v2.1.5です。


ファイルに何も変更を加えておらず、
Clean → Buildを行った際に発生したので何がなんだかです。



エラーが発生しているファイルは、
CCDataVisitor.h
で、
#include <string>

の箇所でエラーが出ました。


ググると同じようなエラーに遭遇した人がたくさんいるようですが、
僕の場合は、

ビルド時にCCDatavisitor.hの#include で'string' file not foundというエラーが突然出るようになってハマったAdd Star


この方と同じ症状で、
Blockクラスを作成していました。

なぜだか理由は分かりませんが、
上記ブログと同じようにBlockクラスを削除して、別のクラス名にするとエラーがなくなりました。



以上でぇぇぇぇぇす。


2014年10月2日木曜日

Xcode6(v6.0.1)でアーキテクチャarmv7sがはずされてしまう。

どうも、俺です。
しばらくぶりのブログです。忙しかったです。


さて、iOS8もリリースされXcodeも新たに6系が出てきました。
が、これまで通りの設定のままXcode6でビルドすると、armv7sでビルドができません。

これは、TARGETS>Build Settings>Architectures>Architecturesのデフォルトの設定にある
Standard Architectures (armv7, arm64)
が原因です。

これでは、いくらValid Architecturesにarmv7sを書いても
そのバイナリは生成されません。


対応するには、
先ほどのArchitecturesを選択し、
Other...
から「armv7s」を追加しましょう。


あとは、Valid Architecturesにarmv7sを記入しておけばOKです。


以上でぇぇぇぇぇぇす。

2014年5月22日木曜日

cocos2d-x CCSprite(テクスチャ)の軽量化

どうも、俺@仕事中です。

今日はcocos2d-xで頻繁利用するCCSprite(またはテクスチャ)の軽量化についてめも。
軽量化というのは、ファイルサイズ的な意味ではなくパフォーマンス面での軽量化という意味です。
ファイルサイズ的な意味での軽量化については最後に記します。

CCSpriteで画像生成するとけっこうなメモリを消費します。
けっこうなメモリとはどのくらいかと言うと、一般的なpng画像(24bitフルカラー)の場合、
1pxあたり4byte(赤8bit + 緑8bit + 青8bit + アルファ8bit)になります。
例えば200x200(px)のpng画像の場合、
200 x 200 x 4byte = 160000byte = 156.25KB
必要です。

なのですが、iPhoneや(ほとんどの?)Android端末で画像を処理する場合、
(2014.5.22修正 iPhoneやAndroidで実際にどのようにメモリ確保されるか不明)
利用するハードウェアによって、
画像(テクスチャ)のメモリは、2の累乗のサイズで確保されます。
どういうことかと言うと、
上の200x200サイズ画像の場合、256x256サイズとしてメモリ確保されるため、
消費メモリは
256 x 256 x 4byte = 262144byte = 256KB
になります。
なんと、これだけで約100KB無駄なメモリ領域が発生してしまいます。

500x600サイズ画像の場合は、
512 x 1024 x 4byte = 2097152byte = 2048KB
になります。
約900KB無駄なメモリ領域が。

画像を大量に使用するゲームアプリなどだと、かなり無駄なメモリが消費されてしまうことになります。


そこでこの問題の解決方法(1)として、スプライトシートを使いましょう。


スプライトシートは複数の画像をまとめて一つの画像として扱うため、
上記で述べたような無駄なメモリ領域というのを極力縮めてくれます。

次に解決方法(2)ですが、pngを出力する際に
透過を使わない → png24で出力
画像が荒くても構わない → png8で出力
という方法もあります。
png24は、24bitフルカラーで透過利用不可になります。
png8はGIFと同じ256色になります。

または、cocos2d-x側で、
    // 透過使わない
    CCTexture2D::setDefaultAlphaPixelFormat(kCCTexture2DPixelFormat_RGB565);
    // 減色させる(赤4bit + 緑4bit + 青4bit + アルファ4bit)
    CCTexture2D::setDefaultAlphaPixelFormat(kCCTexture2DPixelFormat_RGBA4444);
を呼び出しておく、という方法もあります。

このpng8で出力、またはkCCTexture2DPixelFormat_RGBA4444の設定は非常に効果的なのですが、画質が目に見えて荒くなるのが分かるのが残念です。
特にグラデーションは目も当てられません。

そこで、TexturePacker(基本有償)というツールを使いましょう。

有償なだけにとても高機能で、
TexturePacker上で画質を上述したRGBA4444に減色出来ます。
またすごいのが、画質が落ちた画像ファイルをディザリングという機能でキレイに加工してくれます。

例えば下の画像はRGBA8888の綺麗なままのpng画像。
※見やすいように拡大表示しています。

これをRGBA4444に画質を落とすと、
のようにグラデーション部分に荒い線が浮き出てしまいます。

これにディザリングをかけると、
のようになります。
荒いポツポツが目立ちますが、
拡大表示していることが原因で、実物サイズにすると
ほらキレイ。
目を細めてみると ほぼ元画像との違いなんて分かりません。

ちなみに、RGBA4444画質の元サイズはこちら。
うーん、、、
画像が小さいからあまり違い分からないですが、
やっぱりグラデーションが汚いです。そう思って下さい。

というわけでTexturePackerを使えば、
スプライトシートを生成できるだけでなく、画質の調整もできちゃうのでオススメです。



冒頭に書いた「ファイルサイズ的」な軽量化についてですが、
MacだとImageOptimがオススメです。

いろんなアルゴリズムを駆使して画像ファイルを圧縮し、ファイルサイズを小さくしてくれます。
ものによっては60%以上ファイルサイズが軽量化することもあります。
配布するアプリサイズが小さくなるので良いですね。
メモリへのロードも早くなるのかな?


あとは、CCSpriteBatchNodeを利用して、描画も軽量化させると見違えるほどアプリが軽くなります。

以上でぇぇぇぇぇす。

2014年4月17日木曜日

[cocos2d-x] CCClippingNodeで画像をくり抜く

どうも、俺@もう帰るで。

今日はcocos2d-xのCCClippingNodeを使うめもめも。
※cocos2d-xはv2.1.5

先日、「スライディングフロッグ」というゲームアプリをリリースしました。
iOSはコチラ
Androidはコチラ


このゲームの結果画面で、メダルが穫れたときにメダルをキラリっと処理しているのですが、
そこでCCClippingNodeを使っています。



では、どう使うのか、サンプルコードを記していきます。

まず前処理として、iOS側ではAppController.mmの
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions NS_AVAILABLE_IOS(3_0);
メソッドを変更する必要があります。

EAGLViewインスタンスを生成する箇所を、
    EAGLView *__glView = [EAGLView viewWithFrame: [window bounds]
                                     pixelFormat: kEAGLColorFormatRGBA8
                                     depthFormat: GL_DEPTH24_STENCIL8_OES
                              preserveBackbuffer: NO
                                      sharegroup: nil
                                   multiSampling: NO
                                 numberOfSamples:0 ];
と変更します。

次に、結果画面を表示するシーン(ResultScene.cppとする)の処理です。
1)メダルSpriteを置く
CCSprite *medalSprite = CCSprite::create("medal.png");
// 適当なpositionに
medalSprite->setPosition(ccp(100, 100));
this->addChild(medalSprite);

2)光らせるSpriteを用意する
CCSprite *content = CCSprite::create("effect.png");
// 左から右へ動かすので、メダルの左側へ
content->setPosition(ccp(medalSprite->getPositionX()-medalSprite->getContentSize().width,
                         medalSprite->getPositionY()));

3)マスクする画像(メダル)を用意する
// 上記のmedalSpriteとは別に用意する
CCSprite *stencil = CCSprite::create("medal.png");
// メダルSpriteと同じpositionに
stencil->setPosition(medalSprite->getPosition());

4)CCClippingNode生成する
CCClippingNode *clippingNode = CCClippingNode::create();
clippingNode->setStencil(stencil);
// 小さい値にする
clippingNode->setAlphaThreshold(0.01f);
// 光らせるSprite
clippingNode->addChild(content);
// アンカーポイントをセットしておく
clippingNode->setAnchorPoint(ccp(0,0));
// 画面の左下へsetPosition()する
clippingNode->setPosition(ccp(0,0));
// 念のため、CCClippingNodeのサイズを画面全体に..不要?
clippingNode->setContentSize(CCSize(CCDirector::sharedDirector()->getWinSize().width,
                                    CCDirector::sharedDirector()->getWinSize().height));
this->addChild(clippingNode);

5)光らせるSpriteを左から右へ動かす
content->runAction(CCMoveBy::create(0.5f,
                                    ccp(medalSprite->getContentSize().width, 0)));

これで出来るはず(!?)です。

ちなみにAndroidの場合は、Cocos2dxActivity.javaを編集します。
    public Cocos2dxGLSurfaceView onCreateView() {
//      return new Cocos2dxGLSurfaceView(this);
        Cocos2dxGLSurfaceView glSurfaceView = new Cocos2dxGLSurfaceView(this);
        glSurfaceView.setEGLConfigChooser(5, 6, 5, 0, 16, 8); 
        return glSurfaceView;
    } 


以上でぇぇぇぇぇす。

2014年4月5日土曜日

cocos2d-x CCLocalizedStringを使ってローカライズ対応する

どうも、俺@休み中です。

 cocos2d-x(v2.1.5)で開発したゲームアプリもローカライズ対応させよう、
ということで、 有志の方がgithubで公開しているCCLocalizedStringを使わせてもらいました。

sue602/CCLocalizedStringDemo

まず、githubからcloneしてから
CCLocalizedString.cpp/CCLocalizedString.hをドラッグ&ドロップでプロジェクトに放り込みます。

git clone https://github.com/sue602/CCLocalizedStringDemo.git

使い方はとてもシンプル。
例えば日本語圏(japan.png)・英語圏(english.png)でそれぞれ違う画像を表示させたい場合は、
表示させたいSceneで、

#include “CCLocalizedString.h”

... 中略 ...
CCSprite *someSprite = CCSprite::create(CCLocalizedString(“FILE_NAME”, “some_comment"));
とします。
第1引数(”FILE_NAME")が変換対象となるキーです。
第2引数はコメント?

次に、ローカライズ用の設定ファイルを言語ごとにResource/フォルダに用意します。
今回は日本語と英語なのでLocalized_jpとLocalized_enになります。
それぞれのファイルに、
・Localized_jp
FILE_NAME = “japan.png”;

・Localized_en
FILE_NAME = “english.png”;

のように “キー” = “値” というフォーマットで記述します。

これで端末の言語設定によって使われるファイルを切り替えられます。

ただ、このままだと日本語・英語圏以外の言語環境でアプリを起動した場合、
ファイルが見つからずにクラッシュしてしまいました。
(やり方間違えてるのかな、、)
なので、CCLocalizedString.cppを少しいじります。

    // Get data of file
    fileContents = CCFileUtils::sharedFileUtils()->getFileData( fullPath.c_str( ) , "rb", &fileSize );

    // ここから
    if (fileContents==NULL) {
        // ファイルがない場合はLocalized_enを読み込む
        fileContents = CCFileUtils::sharedFileUtils()->getFileData( "Localized_en", "rb", &fileSize );
    }
    contents.assign(fileContents,fileContents+fileSize-1);
こうしておけば、対応していない言語環境の場合は
Localized_enを読み込むことが出来ます。


以上でぇぇぇぇぇす。

2014年1月15日水曜日

Xcode cannot run using the selected device

どうも、俺です。

Xcodeでビルドしようとした際に
「Xcode cannot run using the selected device」というエラーが出てビルド出来ないあなたへ。

"Xcode cannot run using the selected device"に苦しんだ数日間 - マキシぐんだんの中の人のブログ
に同様の問題の対応方法がありますが、僕の場合は少し違いました。

Info.plistの"Target Membership"にチェックが入ってしまっていたことが原因。
チェックを外して解決しました。


以上でぇぇぇぇぇぇす。

2013年12月4日水曜日

[cocos2d-x] CCSpriteの画像を切替える

どうも、俺@眠いです。

CCSpriteのテクスチャ画像をA→Bへ切り替える方法をメモ。


// まず最初の画像 a.png
CCSprite *aSprite = CCSprite::create(“a.png”);

// b.pngへ切り替える
aSprite->setTexture(CCTextureCache::sharedTextureCache()->addImage(“b.png”));
aSprite->setTextureRect(CCRectMake(0,0,aSprite->getContentSize().width, aSprite->getContentSize().height));

もしCCSpriteFrameCacheやCCSpriteBatchNodeを使っている場合は、
// 何らかのスプライトシート
CCSpriteFrameCache::sharedSpriteFrameCache()->addSpriteFramesWithFile(“a.plist”, “a.png");

// 最初の画像 a.png
CCSprite *aSprite = CCSprite::createWithSpriteFrameName(“a.png”);

// b.pngへ変える
CCSpriteFrame *spriteFrame = CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(“b.png”);
aSprite->setDisplayFrame(spriteFrame);

以上でぇぇぇぇぇす。