cocos2d + 非同期 コメント付き
TRANSCRIPT
非同期
坂本一樹@splhack
cocos2d + 非同期
Loading
Loading.......
ローディングで画面がとまる
非同期で解決
非同期とは?
@yuroyuro: 31 May 2011
『非同期って、「オマエ同期入社じゃねーしwww 中途乙www」とか言われてぼっちになることですか』
非同期とは
http://twitter.com/#!/yuroyoro/status/75399664496680960
cocos2d メインループ
cocos2d デフォルトでCADisplayLink
RunLoopベース
非同期話の前に、メインループの話。cocos2dでもRunLoopベース。
CADisplayLink とは?
ディスプレイのリフレッシュに同期してRunLoopでイベントを発生させる代物
ディスプレイのリフレッシュ?
VSYNC
VSYNC
オブジェクトを動かしているシーンで、VSYNC無視して画面更新すると、オブジェクトがぶったぎれて見える
VSYNC
Vertical Synchronizing signal
垂直同期信号
ブラウン管テレビ 走査線
VRAMから読みだした絵をブラウン管に反映する
垂直同期信号って何? ブラウン管テレビの時代までさかのぼりますビームが左上から右下にかけて徐々に動いて、VRAMをブラウン管に反映していく一番下まで行って、一番下から一番上にもどるとこを垂直帰線区間。この間、絵は更新されない
VSYNC
垂直帰線区間中に描画するために垂直同期信号に同期させる
ビームが戻る垂直帰線区間内に画面を更新させるためにVSYNCは存在する垂直帰線区間外にVRAMを更新すると残念なことになる。iPhoneでも基本同じ。ブラウン管じゃなくて液晶ディスプレイ。
CADisplayLink
RunLoopがVSYNCに同期
CADisplayLinkを使うと、RunLoopがVSYNCに同期してループする
CADisplayLink
iOSでは 1/60秒
16.666ミリ秒
60FPS
1回のループの時間が1/60秒
1/60秒以上の仕事
次のVSYNCまで待機
1/60 → 2/60(1/30) → 3/60(1/20)→ 4/60(1/15) → ...
フレームレート低下!
1/60 ぬめぬめ動く
データをロード
RunLoopの実行を止めてしまう(Blocking)
データをロードしてRunLoopをブロックフレームレート低下どころの話ではない画面止まっちゃう
データをロード
RunLoopの実行を止めてしまう(Blocking)
完全なる悪
データをロードしてRunLoopをブロックフレームレート低下どころの話ではない画面止まっちゃう
データを非同期でロード
RunLoopの実行を妨げない
画面停止しない
完全なる善
cocos2dでテクスチャを非同期ロード
CCTextureCache- (void)addImageAsync:target:selector:
まずやっかいなのがテクスチャを非同期で読み込む方法。でもcocos2dだと簡単です。
addImageAsyncを実際にどう使うか、この本を読んでいただくか、ぐぐってもらうとして
addImageAsync 実装
•スレッド起動•起動したスレッド上でGL APIを 呼ぶためのコンテキストを準備 (EAGLContext sharegroup)
どういう実装になっているか
addImageAsync 実装
•イメージデータ読み込み•OpenGL ES テクスチャに変換•glTexImage2D (準備したGLコンテキストが実現)
通常メインスレッド以外でOpenGL ES APIを呼び出せば例外発生
addImageAsync 実装
•メインスレッドで コールバック呼び出し
メインループを止めない!
“ 極論をいえば、ユーザーインターフェースの更新など メインスレッドで実行しなければならない処理だけ RunLoopおよびMain Queueで実行し、それ以外の処理は Global Queueまたは後述のSerial Queueで実行すべし ”
iOS 4プログラミングブック マルチスレッドの章
Grand Central Dispatch
GCDを使おう!
何はなくとも iOS 4 以降専用
Grand Central Dispatch
Global QueueSerial Queue
addImageAsync 呼び出しは安全?
安全
ただし、コールバックは呼び出し元ではなく、メインスレッドで呼び出される
Grand Central Dispatch
iOS 4プログラミングブックの第5章をぜひ読んでくださいませ
おしまい