夏までにiPhone アプリつくってみっか!

趣味でiPhone/Androidアプリを開発し、日々勉強した事を書いています。オープンワールド系レースゲームをUnityで開発中です。

【cocos2d】テクスチャーをキャッシュに先読みしてゲーム中に画面が一瞬止まるのを防ぐ方法

ゲームで使うテクスチャーが多くなってくると1枚のスプライトシートに収まらなくなり、複数のスプライトシートの分ける必要が出てきます。
iPhone4の最大テクスチャーサイズは2048x2048らしいのでこれをリミットとすると、私の偽スペハリの場合はボスのテクスチャーが入らなくなってしまいました。
(ボスがダメージを受けると色が変わって行くのですが、これを全て別テクスチャーとして用意しているので結構な数のテクスチャーになっています。)

早速新たなスプライトシートを作成して実行してみると、ボスが登場するときに一瞬、多分0.3秒くらい、画面が止まるようになってしまいました。
どうやら、ボス用に作ったスプライトシートから初めてテクスチャーを使うときにテクスチャーがキャッシュにロードされるのが原因のようです。

1枚のスプライトシートを使っているときはゲーム開始時にロードされるので気がつきませんが、ゲーム中にロードが入ると明らかにカクッとなるので非常に不愉快です。

これを防ぐにはゲーム開始時にボス用のテクスチャーも明示的にキャッシュしてあげれば良さそうです。
普通にキャッシュする場合はゲーム開始時に、

 [[CCTextureCache sharedTextureCache] addImage:@"texture.png"];

としてやればOKなのですが、スペハリのようにノンストップでどんどんステージが進んで行くゲームの場合、画面を一瞬たりとも止めずにステージ毎に必要なテクスチャーを読んで行く必要があります。

その場合は、

[[CCTextureCache sharedTextureCache] addImageAsync:@"texture.png" withBlock:^(CCTexture2D *tex) {
    // テクスチャーロード完了時の処理
}];

のように非同期でロードすることで画面を止めずにゲームを進行できます。
上の例ではブロックに何も処理を入れていませんが、テクスチャーのロードが完了した時点で実行したい処理があればここに入れておきます。

なお、このメソッドを使うと

cocos2d: deallocing <CCObjectWith2Params: 0x1654cef0>

というログが表示されるようになると思います。
これは、「ブロックオブジェクトが解放された」というログのようです。
(cocos2d/supportフォルダーのNSThread+performBlock.mの中で出しています。)
ということで、特に気にしなくても良さそうです。
https://itunes.apple.com/jp/app/travelshooting-jp-toraberushutingu/id917570972?mt=8&uo=4&at=10laCt
https://itunes.apple.com/jp/app/beecluster-wu-liaono-zongsukurorushutingugemu/id663801586?mt=8&uo=4&at=10laCt