Ameba事業本部 SmartPhoneDivision PiggGameつりポン!制作チーム
Ameba事業本部 SmartPhoneDivision PiggGameつりポン!制作チーム
• つりポン! の紹介 • Flash & cocos2dによる開発 • cocos2d高速化と最適化
本日のお題
• 2010夏まで携帯電話の組込みエンジニア"
• 2010秋ごろからiOSに手を出す • UIKitを使ったゲームや Ameba tappieの開発
• 2011春 つりポンチームへ cocos2dは初めて
自己紹介
つりポン!の評価
1万7千件の評価
10日で10万DL
アプリの紹介
• Twitterによる拡散
ソーシャルメディアによるバイラル
• 完全無料 → 課金アイテム、広告なし"
• アメーバピグ → デザイン、アニメーション
• ストレスフリー → 軽快さ、ゲームバランス、アプリの品質
• App Storeのレビュー誘導 → 楽しんでるユーザにレビューを書いてもらう
高評価の理由
• 主に通信処理結果のハンドリングのみ → ◯◯モードとした場合の不安定さを懸念
• ポイントなどのデータはローカル保存 → 元々はサーバだったので結果画面で オフライン時のみローカルに保存していた
• クエスト、ランキングはオンラインのみ
オフライン対応
• ほぼ全ての機能を非会員でも遊べる • 会員と非会員の差別化 • タイトル画面の対応のみ →サーバによるポイント管理の排除
非会員対応
FlashDeveloperがつりポン!で何をやったか。 cocos2dとFlashと。
Ameba事業本部 interaction designer 新井 隆祥
自己紹介
• 2000~2006までサラリーマン 固めの役所的な感じの所で働いてました。
• 2006~2010までWebサイト制作 Webプロデューサー→Webディレクター→FlashDeveloper・HTMLコーダー(サイトデザインも少し)→フリーランスのWeb制作
• 2011.6~CyberAgent,inc勤務 友人の紹介でネイティブの世界に
お話する内容について
• 画像の管理 途中からプロジェクトにアサイン。まず全体を知るためにここから。
• texturepackerを知る そもそも「テクスチャとは」とググるところから。
• ガチャ部分の構築 アニメーション的な振り返り。
司令: 画像の管理!確実に最速で!
• 大量の画像を書き出す IllustratorやFireWorksで作られたデザインをpngにする簡単なお仕事。
クリア: 画像の管理!確実に最速で!
1.一度Photoshopにまとめる。2.画像名はレイヤーで管理して、バッチで1発書き出し。
png.jsx
texturepackerを知る
ゲーム開発をしている人には馴染みのあるものかもしれませんが、Webサイト中心にやってきた自分には最初ピンとこなかったです。読み込んだ1枚のpngに、画像が隙間なく敷き詰められていて、 それをplist(中身はxml)に書いてある座標から呼び出すという便利なものです。
&
pngファイル plist
司令: texturepackerをうまく使え!
度重なる仕様変更によるデザイン修正。そこにひもづく再書き出し。 同じ画像が別のデザインに変わったり、そもそもなくなったり、管理が面倒。 それをほんのりでも便利にする機能ややり方があります。
・AutoSD・Spriteはフォルダ管理がステキ!
AutoSD!?
・AutoSD Retina用の高解像度画像と3G用の画像を同時に書きだす。それにより、高解像度用画像には"-hd"という接尾辞がつき、3G用の画像は、scaleが0.5になる。
高解像度(Retina)用画像と、通常画像が同時に書き出される。 AutoSDのチェックを入れる
(マウスオーバーでヒント表示あり)
Spriteはフォルダ管理がステキ!
・ Spriteはフォルダ管理がステキ! フォルダ(Finder上)での画像の管理が可能に。Finder上でdeleteすると、texturepacker上でも自動で消えている。(要再書き出し)
展開可能。 Finder上での画像がここに表示 基本的にFinder側を意識する事になるので管理がしやすくなる。
司令: 見ていて飽きないガチャを作れ! cocos2dを使ってな!
画像の管理ばかりやっていたわけではありません。 FlashDeveloperとしての一番の見せ場と入社してからの集大成が8月末に。
まずはFlashで動きを作ってテンションを上げる ガチャのアニメーションは大きく3つにわかれます。 1.色を選ぶ 2.ガチャを出すアニメーション 3.結果表示
ガチャトップ画面
1.色を選ぶ(ガチャ本体) 2.ガチャを出すアニメーション 3.ガチャ結果表示
この中で、Flashで細かく動きをつける必要があるのは、 「1.色を選ぶ(ガチャ本体)」と「2.ガチャを出すアニメーション」になります。
ガチャトップ画面
1.色を選ぶ(ガチャ本体) 2.ガチャを出すアニメーション 3.ガチャ結果表示
まずはFlashで動きを作ってテンションを上げる
ガチャトップ画面
1.色を選ぶ(ガチャ本体) → 肝になる部分は、ガチャのカプセルの揺れかと思い、 揺れが止まる長さが微妙に違う2パターンをFlashで作成しました。
&
色を選んだ後のロングVer. ガチャ選んだ時のショートVer.
まずはFlashで動きを作ってテンションを上げる
2.ガチャを出すアニメーション → 肝になる部分は、ガチャのカプセルが出るところかと思い、 給湯室でこっそりガチャの動きをシュミレーション。
ガチャトップ画面
口を開けるアニメーションとボールを出すアニメーションをFlashで二つ作って後で連結
&
まずはFlashで動きを作ってテンションを上げる
自作AIRツールで座標の抽出
実際に、Flash(swf)からの座標の抽出は お手製のロジックを利用して、 AIRで簡単にmとhファイルが自動で書き出せるツールを作成しました。
ガチャトップ画面
ということで、出来たガチャです
ガチャトップ画面
Flash上でのレイアウトをcocos2dで再現
• 座標系の違いを補正する スクリーン座標 ー> デカルト座標 違うところはy座標の加減算結果が 上下逆になるところと原点が TopLeftとBottomLeftになるというところ
• そこだけ補正すればFlash上のレイアウト結果を cocos2dで再現するのは余裕
flashでy座標に-1かけてあげれば補正完了 ※cocos2dでは座標計算はretina用でも3gの画角で行わ
れるので Flash上では960:640でレイアウトして/2してます。
Flashから必要なDataを cocos2dで使える形に整形して抜き出す
• 座標補正した結果をcocos2dで使える形にして .h/.mで書き出す 作業補助用AIRアプリを作りました。
• これでFlash上のレイアウトが そのまんまcocos2dに移植出来る!
• 最終的に.mのinitメソッドで インスタンスの配置までした状態の CCNode継承クラスが 書き出されるようにしました。 (これFlashからAIRを経由しての自動生成です)
• 工数めっちゃ減るしDesignerとか なんなら内定者でも レイアウト操作できちゃう!!
Flashから必要なDataをcocos2dで使える形に整形して抜き出す
Flash->cocos2dへのレイアウト、 アニメーション移植完成!
cocos2dはFlashDeveloperにやさしい!
ガチャトップ画面
FlashDeveloperとして、とてもすんなり入れるフレームワークで有ることは
間違いないです。
いっしょに触って盛り上げていきましょう!
• 1999 年からこれまで、 PC, PS, DS といった コンシューマーゲーム開発をしていました。
• 知り合いの紹介で最近中途入社しました。 • iOS の開発は初めてでしたが cocos2d で処理が抽象化されていたので すぐに慣れました。
自己紹介
• 描画処理の高速化 • テクスチャロードの非同期化 • メモリー使用量の削減 • モーション演算処理の高速化
cocos2d を利用した最適化と高速化
• OpenGL の描画関数の呼び出し時の オーバーヘッドが大きい→ 関数コールの回数が増えるほど、 極端に重くなる傾向があります。
• TexturePacker で複数のテクスチャを1枚に結合
• CCSpriteBatchNode で複数の CCSprite の描画を統合
iPhone の OpenGL の傾向と対策
対策
• [[CCTextureCache sharedTextureCache] addImage:@"Hoge.png"]; [[CCSpriteFrameCache sharedSpriteFrameCache]addSpriteFramesWithFile:@"Hoge.plist”]
TexturePacker で生成した SpriteFrame の初期化
• // 各 CCSprite の初期化と CCSpriteBatchNode への登録 CCSprite* hoge0Sprite = [CCSprite spriteWithSpriteFrameName:@"Hoge0.png"]; CCSprite* hoge1Sprite = [CCSprite spriteWithSpriteFrameName:@"Hoge1.png"]; CCSpriteBatchNode* spriteBatchNode = [CCSpriteBatchNode batchNodeWithTexture:hoge0Sprite.texture]; [spriteBatchNode addChild:hoge0Sprite]; [spriteBatchNode addChild:hoge1Sprite];
• cocos2d の非同期ロード関数を使用して、 テクスチャ生成を非同期化しました。( addImageAsync )
• シーン遷移のフェードアウト開始時に テクスチャロードを行うことにより、 ユーザーの待ち時間を減らしました。
テクスチャロードの非同期化
• // TexturePacker で出力した結合テクスチャと plist の初期化 CCTextureCache sharedTextureCache] addImageAsync:@"Hoge.png" target:self selector:@selector(imageLoaded:)]; // ※ ロード完了通知後 CCSprite* hogeSprite = [CCSprite spriteWithFile:@"Hoge.png"];
addImageAsyncの使い方
テクスチャフォーマットの調整
• cocos2d はテクスチャフォーマットが標準でA8R8G8B8 になっています。
• つりポンでは、これを テクスチャごとに調整することにより、 メモリー使用量を抑えました。
対策
• // addImage / addImageAsync の前に設定 [CCTexture2D setDefaultAlphaPixelFormat:kTexture2DPixelFormat_RGBA4444]; // テクスチャロードの開始 [[CCTextureCache sharedTextureCache] addImageAsync:@"Hoge.png" target:self selector:@selector(imageLoaded:)];
テクスチャフォーマットの調整方法
cocos2d のモーション制御の最適化
• CCSpawn や CCSequence は処理コストが大きいので注意 → 特に、人体など複雑なものには不向きです。
• モーション制御クラスを独自に実装 & NEON による並列演算 → 後ほど検証結果をまとめたものをお見せします。
対策
• -(CCSpawn *) setX :(float)posX setY:(float)posY setR:(float)rot speed:(float)speed { CCMoveTo *move = [CCMoveTo actionWithDuration:speed position:ccp(posX,posY)]; CCRotateTo *rotate = [CCRotateTo actionWithDuration:speed angle:rot]; CCSpawn *spawn = [CCSpawn actions:rotate, move, nil]; return spawn; } -(CCSequence*) initMotion { CCSpawn *s1 = [self setX:-1.425 setY:21.225 setR:0 speed:0.04]; CCSpawn *s2 = [self setX:-1.275 setY:21.25 setR:-1 speed:0.04]; CCSpawn *s3 = [self setX:-1.125 setY:21.25 setR:-1 speed:0.04]; CCSpawn *s4 = [self setX:-0.95 setY:21.275 setR:-1 speed:0.04]; return [CCSequence actions:s1,s2,s3,s4,nil]; }
モーション制御部分の最適化前のコード
• // キーフレーム情報は int16_t に変換してメモリ使用量を削減 typedef struct { int16_t posX, posY, rotation, scale; } MotionParam; // モーションデータの定義( 単純な C 配列 ) #define MPV( VALUE ) (int16_t)((VALUE) * 256.0) static MotionParam motionParam[] = { { MPV( -1.425 ), MPV( 21.225 ), MPV( 0 ), MPV( 1 ) }, { MPV( -1.275 ), MPV( 21.25 ), MPV( -1 ), MPV( 1 ) }, { MPV( -1.125 ), MPV( 21.25 ), MPV( -1 ), MPV( 1 ) }, { MPV( -0.95 ), MPV( 21.275 ), MPV( -1 ), MPV( 1 ) }, };
モーション制御部分の最適化後のコード
• // 線形補間関数( NEON による最適化 ) float32x4_t MotionInterpolate( MotionParam* src, MotionParam* dst, float ratio ) { float src_val[4] = { (float)src->posX, (float)src->posY, (float)src->rotation, (float)src->scale }; float dst_val[4] = { (float)dst->posX, (float)dst->posY, (float)dst->rotation, (float)dst->scale }; float32x4_t src_vec = vld1q_f32( src_val ); float32x4_t dst_vec = vld1q_f32( dst_val ); // ( src + ( dst - src ) * ratio ) * ( 1.0f / 256.0f ) return vmulq_f32( vaddq_f32( src_vec, vmulq_n_f32( vsubq_f32( dst_vec, src_vec ), ratio ) ), vdupq_n_f32( 1.0f / 256.0f ) ); }
モーション制御部分の最適化後のコード(続き)
コンフィグの微調整
• つりポンでは ccConfig.h の一部を以下のように変更したところ、描画負荷が軽減されました。 // #define CC_USES_VBO 1 #define CC_USES_VBO 0
• Xcode の Instruments の Time Profiler を使用して検出しました。
検出方法
• 関数単位で処理時間の一覧を表示してくれるので、 ボトルネックの早期発見に役立ちます。 最適化は、負荷の高い場所から順に、 常に計測しながらを心がけましょう。
Time Profiler について
• 実際に以下のような条件で負荷テストを行いました。 ピグを同時に 64 体描画、パーツ数 11、αブレンド有効。 iPhone 4 ( Retina ) で検証、高解像度テクスチャを使用。 最適化前と後の2パターンで、それぞれ計測してみました。
ピグの描画負荷比較
最適化前の計測結果
停止状態(アニメーション無効)のピグを 64 体表示 5.4 ~ 5.7 FPS
歩行状態(アニメーション有効)のピグを 64 体表示 3.7 ~ 5.6 FPS
CCSprite をパーツごとに単体描画
モーション制御は CCSequence & CCSpawn を使用
検出方法
最適化後の計測結果
停止状態(アニメーション無効)のピグを 64 体表示 49.6 ~ 51.4 FPS
歩行状態(アニメーション有効)のピグを 64 体表示 44.5 ~ 46.0 FPS
CCSpriteBatchNode を使用して描画
モーション制御は NEON で最適化された 独自クラスを使用
ccConfig.h の CC_USES_VBO を 1 から 0 に変更
検出方法
ピグの描画負荷比較
まとめ
• テクスチャは描画単位で 1 枚にまとめ、CCSpriteBatchNode で描画しましょう
• 座標計算などジオメトリ演算処理を大量に行う場合は、NEON など SIMD を用いて 最適化することをおすすめします
• ccConfig.h のオプションを調整すると、 場合によっては大幅に高速化されます
参考資料
• cocos2dで作る iPhone&iPadゲームプログラミング 出版社: インプレスジャパン (2011/6/24) ISBN-10: 4844330411 ISBN-13: 978-4844330417
• Open GL ES 2.0 プログラミングガイド 出版社: ピアソン桐原 (2009/11/1) ISBN-10: 4894714396 ISBN-13: 978-4894714397
参考資料
• iOS デバッグ&最適化技法 for iPad/iPhone 出版社: 秀和システム (2010/11/25) ISBN-10: 4798028053 ISBN-13: 978-4798028057
• iOS SDK HACKS 出版社: オライリージャパン (2010/10/23) ISBN-10: 4873114721 ISBN-13: 978-4873114729
おすすめ!
• iOS OpenGL ESプログラミングガイド - Apple Developer http://developer.apple.com/jp/devcenter/ios/library/documentation/OpenGLES_ProgrammingGuide.pdf iOS & OpenGL での最適化 Tips が数多く載っています。
• ARM Information Center http://infocenter.arm.com/help/index.jsp NEON のコンパイラ組み込み関数の説明が掲載されています。 ARM のニーモニックも一読しておくと最適化のヒントになります。
• PowerVR Insider Developer Programme
http://www.imgtec.com/PowerVR/insider/powervr-insider.asp OpenGL ES から PowerVR を扱うためのリファレンスやサンプルが数多く掲載されています。 PVRTC 関連のツールやライブラリ、資料も豊富です。
参考資料
ご清聴ありがとうございました。