2015年12月24日木曜日

error: Error retrieving parent for item: No resource found that matches the given name '@android:style/ Theme.Material.Light.DialogWhenLarge.NoActionBar'.

どうも、俺です。

eclipseを使ってAndroidアプリ開発中に、
組み込んだgoogle-play-serviceでタイトル通りのエラーがでたときの対応。

error: Error retrieving parent for item: No resource found that matches the given name '@android:style/ Theme.Material.Light.DialogWhenLarge.NoActionBar'.

eclipseの設定をイジってしまったのだと思いますが、どこをどうイジったのか全く覚えておりません。
修正を色々試みたところ、
StackOverflowに似たようなエラーで困っている人発見!

今回の僕の場合、
appinvite_style.xmlに記述されている
Theme.Material
APIレベル21以上で利用できる、とのことなので、
google-play-serviceプロジェクトの
プロパティ>Android>Project Build Target
をAPI21にして修正完了。


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

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年9月4日金曜日

[Xcode] コマンドラインからipaファイルをエクスポートする

どうも、俺です。

 今日は、アーカイブされたiOSアプリをコマンドラインから.ipaファイルをビルドする方法をメモ。


いつも通りProduct>Archiveします。




オーガナイザーが起動するので、対象のビルドされたアプリを選択しCtrl押しながらクリックし「Show in Finder」を選択。




Finderが起動するので、ファイルのパスとファイル名をメモ。




次に、XcodeのBuild Settings>Code Signingからビルドに使用するプロビジョニングプロファイルの名称(通称?)をメモ。




今回の場合、Releaseビルドをしようと思うので「KabekeriSasuke3_AppStore」をメモ。


あとはビルドコマンドを打ち込むだけ。

xcodebuild -exportArchive -archivePath '.xcarchiveファイルのパス' -exportPath '出力先のファイルパス' -exportFormat ipa -exportProvisioningProfile 'プロビジョニングプロファイルの名称'

なので、今回の場合はこうなります。
xcodebuild -exportArchive -archivePath '/Users/USER_NAME/Library/Developer/Xcode/Archives/2015-09-04/Sasuke3 2015-09-04 16.07.xarchive' -exportPath '/Users/USER_NAME/Desktop/Sasuke3App' -exportFormat ipa -exportProvisioningProfile 'KabekeriSasuke3_AppStore'

こうするとDesktop上にSasuke3App.ipaファイルが出来上がります。


なぜこのような面倒なことをするのか、と言うと理由は2つ。
1つは、例えば受託案件でクライアント所有の証明書やプロビジョニングプロファイルでビルドする際、先方のiTunesConnectのアカウント情報を知らないとXcodeからDistributionビルドできません。
そういう場合に、上の方法でビルドします。

もう1つは、自社アプリをAdHocビルドしようとしたときに、オーガナイザで選択するプロビジョニングプロファイルが「XC Ad Hoc: xxxx〜....」というファイルしか選択できないときがあります。(ありました。)
なぜそうなってしまうのか未だ原因は分かっていませんし、そのプロビジョニングプロファイルでもビルド出来るのですが、
何かしっくりこないので、そういう場合にコマンドラインからビルドしました。

XC Ad Hoc: 〜プロビジョニングプロファイルについて何か知っている方いらっしゃったら教えてください〜m(__)m

以上でぇえぇぇす。

PostgreSQLでスキーマ(テーブル定義)を取得する方法

どうも、俺です。

 PostgreSQLでターミナル上からスキーマ情報を取得したい場合。
$ pg_dump --schema-only DATABASE_NAME > schema.sql



以上でぇぇぇぇす。

2015年9月2日水曜日

Apache(2.4系)のソースインストールで "checking for OpenSSL version >= 0.9.8a... FAILED"が出る

どうも、俺です。

Apacheをソースインストールするときにつまづいたのでメモ。
./configureした際に

checking for OpenSSL version >= 0.9.8a... FAILED
configure: WARNING: OpenSSL version is too old
no
checking whether to enable mod_ssl... configure: error: mod_ssl has been requested but can not be built due to prerequisite failures

が出ちゃった場合。

# yum install openssl-devel

で解決!

※僕の場合、CentOS6.7 Apache 2.4.12でした。

以上でぇぇぇぇす。

2015年6月25日木曜日

PostgreSQLのロック確認方法

どうも、俺です。

PostgreSQLで発生しているロックの確認の方法です。

PostgreSQL:ロックの確認と解除方法

上記にありますが、

SELECT l.pid, db.datname, c.relname, l.locktype, l.mode
FROM pg_locks l
        LEFT JOIN pg_class c ON l.relation=c.relfilenode
        LEFT JOIN pg_database db ON l.database = db.oid
  WHERE datname='{DATABASE_NAME}'
ORDER BY l.pid;

です。

9.6. ロックとテーブル
にあるように、クエリ実行中は数種類のロックがかかっています。

実際に測ってみると、
SELECT文でも AccessShareLockがかかりますが、
これはAccessExclusiveLockモードとのみ競合するとのことなので、
ALTER TALBE, DROP TABLE, VACUUM FULL, LOCK TABLE
以外のクエリに対しては何ら問題ありません。


以上でぇぇぇぇす。

2015年6月24日水曜日

PostgreSQLのキャッシュヒット率計算

どうも、俺です。

PostgreSQLのキャッシュヒット率の計算をググって出てきたのでメモ。

以下のサイトに書いてありました。
稼動統計情報を活用しよう(2)

・テーブルへのキャッシュヒット率の計算
SELECT relname,
   round(heap_blks_hit*100/(heap_blks_hit+heap_blks_read), 2)
   AS cache_hit_ratio FROM pg_statio_user_tables
     WHERE heap_blks_read > 0 ORDER BY cache_hit_ratio;


・インデックスのキャッシュヒット率の計算
SELECT relname, indexrelname,
   round(idx_blks_hit*100/(idx_blks_hit+idx_blks_read), 2)
   AS cache_hit_ratio FROM pg_statio_user_indexes
     WHERE idx_blks_read > 0 ORDER BY cache_hit_ratio;


以上でぇぇぇぇす。


※2015.6.25 追記

postgresql_トラブルシュート
を参考にテーブルキャッシュヒット率とインデックスヒット率を同時に計算できるんじゃないかと考えました。
利用するテーブルはpg_statio_user_tablesです。
SELECT *,
(heap_blks_hit*100) / (heap_blks_read+heap_blks_hit) AS disk_ratio,
(idx_blks_hit*100) / (idx_blks_read+idx_blks_hit) AS idx_ratio
FROM pg_statio_user_tables
WHERE heap_blks_hit >= 1
and schemaname = 'public' ORDER BY idx_ratio;

統計情報を持つテーブルについてはこちら(統計情報コレクタ)を参考に。

ただ、なぜかこのクエリだといくつかのインデックスヒット率は、上述したクエリで算出したものと異なる場合がある。。
なので、修正しないといけない...。


※2015.6.26 追記
キャッシュヒット率の合計平均を出すクエリを作りました。

・テーブルへのキャッシュヒット率平均
SELECT avg (cache_hit_ratio)
FROM
(SELECT relname,
   round(heap_blks_hit*100/(heap_blks_hit+heap_blks_read), 2) AS cache_hit_ratio 
FROM pg_statio_user_tables
     WHERE heap_blks_read > 0) AS foo;

・インデックスヒット率の平均
SELECT avg(cache_hit_ratio)
FROM
(SELECT relname, indexrelname,
   round(idx_blks_hit*100/(idx_blks_hit+idx_blks_read), 2) AS cache_hit_ratio 
FROM pg_statio_user_indexes
WHERE idx_blks_read > 0) AS foo;

統計情報をリセットする場合は
SELECT pg_stat_reset();
を叩けばリセットされます。

設定を変更して統計を取り直したい場合などに使います。

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

以上でぇぇぇぇぇぇす。


2015年1月8日木曜日

64bit(arm64)対応するとJSONKitがエラー[iOSアプリ]

どうも、俺です。

Xcode開発でアーキテクチャにarm64を追加すると
組み込んだ3rdパーティ製ツールのJSONKitからエラーが出てビルドできません。



githubを見ると、JSONKitはかなり長い間更新が止まっており
arm64アーキテクチャに対応していないようです。

この場合は、
該当のエラーが出ている箇所にマウスポインタを併せてクリックし、
エラーを修正してしまえば対応できます。


エラー箇所は2箇所あります。


または、
元のJSONKitをフォークして64bit対応したソースが公開されているので、
そちらでも対応出来ると思います。(※未確認)


以上でぇぇぇぇぇぇす。

amazon