Seasons.NET

ちょっとした技術ブログです

cocos2dで非同期画像読み込みを超絶簡単に実装するCCResourceAsyncLoaderの紹介

みなさんこんにちは。
@cocos2dfan_jpの管理人でKobold2Dオフィシャルメンバー(日本語ドキュメント担当)の@Seasonsです。

cocos2d Advent Calendar 2011 : ATND
という12月1日から25日まで毎日cocos2dに関する記事を公開するイベントに参加しました。


私は、12月5日の記事担当ということで、タイトルの通り
cocos2dで非同期読み込みを簡単に実装するためのライブラリ
CCResourceAsyncLoaderについて紹介します。


リソースを読み込むとき、通常読込みが完了するまで
処理が止まってしまうため、よくある実装として
Now Loadingと文字+黒い背景という
画面を出すという手法が用いられます。


しかし、ユーザーはそのNow Loadingがいつ終わる
という情報をなるべく知りたいものです。


そこで読み込みが完了するまでプログレスバー的な
実装をしたいわけですが、その場合、非同期読み込みという
バックグラウンドで読み込む処理を使う必要があります。
cocos2dでは、Async(非同期読み込み)のAPIが用意されていますが
それでも初めて使う人には敷居が高いです。


では、拙作ではありますがその非同期読み込みをより
簡単に実装するためのCCResourceAsyncLoaderを使ってみましょう。


まず、以下のリンクからcocos2d-extensionsをダウンロードしてください。
Seasons7/cocos2d-extensions - GitHub

Seasons7/cocos2d-extensions - GitHub
Uploaded with Skitch!


ダウンロードして展開すると、次のようなファイル構成になっています。
Path Finder


cocos2d-extensions.xcodeproj
をダブルクリックしてXcodeを起動します。
(Xcodeは、最新版のXcode 4を利用しています)


起動した後、次のようにCCResourceAsyncLoaderTestのサンプルを選んでください。

xcodecapture
Uploaded with Skitch!


サンプルを選んだ後は、先ほどの手順で既にSimulatorビルドを選んでいるので
ビルドしてしばらく待ちます。iPhoneの開発環境が正しくインストールされていれば、
iPhoneシミュレーターが起動して、プログラムが実行されます。


サンプルでは、Now Loading[XX]という文字列が表示されており、
画像が読み込まれるごとにカウントダウンします。
最終的には、Now Loading[0]と表示されて終了です。
お使いのマシンによっては一瞬でプログラムが終了してしまいます。


CCResourceAsyncLoaderを使うための手順は、SlideShareでまとめたので
クリックしながらみてください。


サンプルではloadCompleteメソッドを使い回していますが、
それぞれのリソースが読み込まれた後にそれぞれ異なるメソッドを
呼び出すことも可能です。

もし、プログレスバー的な実装をしたい場合は、
サンプルではresourceCountの数を単純に表示しているところを
(float)loader.resourceCount/(float)loader.maxResouceCount
のようにして現在読み込まれている割合を取得してバーとして
表示すればよいでしょう。


さて、ここから余談です。
サンプルでは一瞬で処理が終わってしまうので、少しコードを変更してみましょう。


次の動画のようにコードを変更してみてください。

実行すると、カウントダウンの様子が見えると思います。
しかし、4-3-2-1->0のようにはなりません。
環境によっては、4-3->0になるかもしれません。

なぜそうなるのか?
次の図をみてください。
CCResourceAsyncLoader306B306430443066.graffle: 30AD30E330F330D030B9 2


CCResourceAsyncLoaderに登録したリソースというのは、
addChildで対象オブジェクトにCCResourceAsyncLoaderを
登録した次のフレームから処理が始まります。

このとき、登録したリソース全てが非同期で同時に読み込み
処理が行われ、それぞれのリソースが読み込み完了した際に
loadComplete(これはサンプルで登録したメソッドです)
メソッドが呼び出されます。


loadCompleteメソッドの中では、現在読み込みが完了したリソースの数を
次のように減らしてからその数を[]内の数字として表示しています。

   CCResourceAsyncLoader *loader = (CCResourceAsyncLoader *)obj;
    loader.resourceCount--;


リソースの読み込み順番には必ず順位がありますから
最初に読み込まれた時にはまだresourceCountが4です。
これを-1するので3となります。


さてここからが重要です。非同期読み込みとは、
先ほどのコードの修正のように2秒間待ったからといって
読み込みも止まっているわけではありません。


当然その2秒間の間に他のリソースが読み込み完了している可能性が
ありますからこのloadCompleteが呼び出し終わった後に、
すぐさまloadCompleteが呼ばれる可能性があります。
このタイミングがその描画フレーム間内に行われれば、
当然resourceCountが-1されてNow Loading...[2]を表示させる
描画コードを発行するかもしれません。


これにより、お使いの環境で、
4-2-0となったり、4-3-0と表示されてしまいます。


あれれ?となりがちなコードですが
描画の仕組みを知っていると納得しやすいと思います。