More Related Content
Similar to Cocos2d-xを用いた "LINE タワーライジング" の開発事例 (20)
Cocos2d-xを用いた "LINE タワーライジング" の開発事例
- 1. Copyright © 2015 Wright Flyer Studios, Inc. All Right Reserved.
Wright Flyer Studios部 西田綾佑
Cocos2d-xを用いた
"LINE タワーライジング" の開発事例
GREE GameDevelopers' Meetup 01
#greegdm01
- 2. Copyright © 2015 Wright Flyer Studios, Inc. All Right Reserved.
• 西田綾佑 (にしだ りょうすけ)
• グリー株式会社 Wright Flyer Studio部
• クライアントリード(エンジニア)
• @hosi_mo
• 塔コード : 4M9EVCBK
• 経歴
• 東京大学大学院情報理工学系研究科 修了
• グリー株式会社(2014年~)
自己紹介
- 3. Copyright © 2015 Wright Flyer Studios, Inc. All Right Reserved.
ゲーム紹介
配信日 : 2015/6/23
ジャンル : RPG、アドベンチャー
プラットフォーム : iOS / Android
おかげさまで事前登録43万人
▼塔はつんでも、人生つむな
▼頭脳系ダンジョンRPG
▼方向音痴の作者が作った、
新しいスタイルのダンジョン探検
- 4. Copyright © 2015 Wright Flyer Studios, Inc. All Right Reserved.
実はDungeon Flickerがベースとなった
- 5. Copyright © 2015 Wright Flyer Studios, Inc. All Right Reserved.
“タワーライジング” リリースまでの開発体制
プロデューサー
1名
クライアントプログラマ
4名
サーバプログラマ
3名
アート
2名
ディレクター(原作)
1名
ゲームデザイナー
2名
PM
3名 16名
- 6. Copyright © 2015 Wright Flyer Studios, Inc. All Right Reserved.
全体スケジュール(14ヶ月)
2015年
3月~ ダンジョンフリッカー公開
2014年
4月~ α開発 10月~ β開発
β開発 ~1月
1月~ LINE連携
4~6月 チュートリアル改善
6月 GA
社内リリース 社内リリース
11月〜ベンダーテスト
ベンダーテスト ~4月
- 7. Copyright © 2015 Wright Flyer Studios, Inc. All Right Reserved.
• Cocos2d-x 3.2
• コーディング環境
• C++ 11
• Mac + Xcode
• 主にiOSの実機開発(手触りを重視)
• Android
• 動作確認 Android 2.3~ (動作保証は現状4.0)
• なにか起きたらlog catを眺めてスレッドを感じる
開発環境
- 8. Copyright © 2015 Wright Flyer Studios, Inc. All Right Reserved.
• libdispatch
• 並列化したい処理だけキューに投げられて便利
• Cricket Audio
• サウンドの再生。安定してる。
• 他プロジェクト(Cocos2d-x)で実績あり
• Jenkins
• 毎日自動でビルドを作って社内チャットに共有
• Hockey App
• ビルド配布
• クラッシュログ収集
要素技術
- 10. Copyright © 2015 Wright Flyer Studios, Inc. All Right Reserved.
• Cocos2d-xで作り直したい
• ダンジョンフリッカーはAdobe Air
• 画面数が少ない
• 複雑な画面が少ない
• 社内ツール : レイアウトローダ(psd -> Cocos2d-x) を使うほどでもない
• 簡素な演出が好まれた
• LWFを使うほどではない
• 当時 : (送りバントと呼ばれたプロジェクト)
• そもそものアサインが少ない(さらにFlashアニメータ自体が社内に少ない)
開発初期(2014年春~夏)
2014年3月にダンジョンフリッカーをリリース
- 11. Copyright © 2015 Wright Flyer Studios, Inc. All Right Reserved.
• UI配置 : エンジニアが頑張る
• UIアニメーション : エンジニアが頑張る
• 演出 : エンジニアが頑張る
結果
oh. . . .
- 12. Copyright © 2015 Wright Flyer Studios, Inc. All Right Reserved.
アサインされたエンジニアが面食らう
- 13. Copyright © 2015 Wright Flyer Studios, Inc. All Right Reserved.
UI配置
おわかりいただけるだろうか?
- 14. Copyright © 2015 Wright Flyer Studios, Inc. All Right Reserved.
タワーライジングは町工場だから
- 15. Copyright © 2015 Wright Flyer Studios, Inc. All Right Reserved.
• UI
• コードに座標打ってもなんとかなる..かも?
• 演出
• runAction()も、Easingもあるじゃないか
• パペットアニメーションの実現は…
開発初期
エンジニアから職人へのジョブチェンジ
- 16. Copyright © 2015 Wright Flyer Studios, Inc. All Right Reserved.
アニメーション
安心してください、書いてますよ
Avatar.cpp
1200行くらい
- 17. Copyright © 2015 Wright Flyer Studios, Inc. All Right Reserved.
なんとかなった理由
①画面がシンプル
- 18. Copyright © 2015 Wright Flyer Studios, Inc. All Right Reserved.
なぜその①
画面の仕様がシンプル
- 19. Copyright © 2015 Wright Flyer Studios, Inc. All Right Reserved.
なぜその①
画面の仕様がシンプル
• すべての画面を同一のコンポーネントでつくる
• アニメーションが共通化できる
• SEが共通化できる
• 基本的に9sliceで作りきれる範囲の装飾
- 20. Copyright © 2015 Wright Flyer Studios, Inc. All Right Reserved.
なんとかなった理由
②仕様書もシンプル
- 21. Copyright © 2015 Wright Flyer Studios, Inc. All Right Reserved.
なぜその②
一枚絵とにらめっこして作り上げられる
• 仕様書が画像一枚(+注釈)
• 位置もこれがマスター
究極的には
エンジニアがこの一枚絵を完コピすれば良い
- 22. Copyright © 2015 Wright Flyer Studios, Inc. All Right Reserved.
なんとかなった理由
③Flashで動いている
- 23. Copyright © 2015 Wright Flyer Studios, Inc. All Right Reserved.
• Flashでmockを作ってくれた♥
• ソース見てC++に書き換える
• ASのBetweenライクなWrapperをC++で実装
なぜその③
新規のこまかい演出の実装
tween = BetweenAS3.parallel(
BetweenAS3.tween(part.Finger, {y:range * -0.5}, {y:range * 0.5}, 0.6, Quad.easeInOut),
BetweenAS3.tween(part.Gesture, {y:range * -0.5}, {y:range * 0.5}, 0.6, Quad.easeInOut),
BetweenAS3.tween(part.Gesture, {scaleY:2}, {scaleX:0}, 0.6, Quad.easeInOut)
);
anim = Sequence::create(Spawn::create(Between::to(finger, "y:200", 0.7, Easing::QuadInOut),
Between::to(gesture, "y:200", 0.7, Easing::QuadInOut),
Between::to(gesture, "scaleX:2,scaleY:2", 0.7, Easing::QuadInOut),
NULL),
NULL);
ActionScript
C++
- 24. Copyright © 2015 Wright Flyer Studios, Inc. All Right Reserved.
なんとかなった理由
④消滅都市先輩がいた
- 25. Copyright © 2015 Wright Flyer Studios, Inc. All Right Reserved.
• クライアントサイド
• 通信
• データベース
• サーバーサイド
• 概ね消滅都市と同等の構成(Silex + MagicSpice)
なぜその④
消滅都市から基本機能を切り出して改良した
エンジニアリングにおける挑戦をしなかった
安全な方向に倒す開発に専念した
その他プロジェクトの偵察を怠らなかった
- 27. Copyright © 2015 Wright Flyer Studios, Inc. All Right Reserved.
• TitleScene
• ログイン処理、データベース構築など
• HomeScene
• ホーム画面 (塔を俯瞰したあの画面)
• DungeonScene
• ダンジョン内
• DecorationScene
• デコレーションする画面
全体の設計
シーン一覧 <CCScene.cpp>
- 28. Copyright © 2015 Wright Flyer Studios, Inc. All Right Reserved.
ステートの分割
UIの動きに見合うステートマシンもどきを設計した
• Layerの管理
• Stack型の状態管理(ゲームロジック)
• Viewのトランジションも自動化
LayerのPush()とPop()で階層的なUIを管理
StateManager::getInstance()->pushState(レイヤー);
StateManager::getInstance()->popState();
- 29. Copyright © 2015 Wright Flyer Studios, Inc. All Right Reserved.
ステートの分割
(例)ダイアログの表示と消去
auto dlg1 = DialogOne::create();
StateManager::getInstance()->pushState(dlg1);
StateManager::getInstance()->popState();
(例)ダイアログ1のコールバックを受けてダイアログ2を表示
auto dlg1 = DialogOne::create();
auto dlg2 = DialogTwo::create();
StateManager::getInstance()->pushState(dlg1, [dlg2](StateEvent se){
if (se.Name == DialogOne::YES) {
StateManager::getInstance()->pushState(dlg2);
}
});
- 30. Copyright © 2015 Wright Flyer Studios, Inc. All Right Reserved.
• 階層的な画面が容易に作れた
• ウィンドウの表示・非表示のアニメー
ションが楽に統一化できた
• UIベタ書きでもなんとか持ちこたえた
階層的なUIの実現
そのおかげで
- 32. Copyright © 2015 Wright Flyer Studios, Inc. All Right Reserved.
• 地道に1フリックごとに状態を保存
• バトル中は特定のタイミングでス
ナップショットをとっている
• ※暗号化しています
オートセーブ機能
ダンジョン内にいる場合いつでもアプリをkillできる
- 33. Copyright © 2015 Wright Flyer Studios, Inc. All Right Reserved.
• グレースケールで書かれたレンガに
画像を乗算してalpha指定
• 横の壁はSpriteを3軸で歪ませて表現
• レンガのパースが厳密でないので鬼の位置調整
デコレーション
乗算でそれっぽく仕上げる
BlendFunc blend;
blend.src = GL_ZERO;
blend.dst = GL_SRC_COLOR;
- 34. Copyright © 2015 Wright Flyer Studios, Inc. All Right Reserved.
• iOS
• Obj-C
• UIImageで頑張る
• Android
• Java
• Bitmap.createBitmapで頑張る
顔はめ込み機能
両OSでNative Bridge先で端末内の画像をcropする
- 35. Copyright © 2015 Wright Flyer Studios, Inc. All Right Reserved.
• GPUによってはRenderTextureで描画が崩れる(ClippingNode. . .)
• スクショを撮る一瞬だけ不必要なnodeを隠した
• 本当はcropしてシェアしたかった
• 全画面スクショで我慢した
画像シェア機能
Utils::captureScreen
this->node->setVisible(false);
utils::captureScreen([this](bool success, const std::string& output) {
this->node->setVisible(true);
}, "capture.png");
- 37. Copyright © 2015 Wright Flyer Studios, Inc. All Right Reserved.
• アクションゲームではない
• 30FPSで問題ない
• 演出が激しくない
• 要求されるものがすくない
• がんばらなくてよかった
パフォーマンス
- 38. Copyright © 2015 Wright Flyer Studios, Inc. All Right Reserved.
• アイテム画像全部で500KBくらい
• アートさんがモンスターも1枚1枚減色してくれた
• アセットダウンロード無しで初期リリースを決意
• 結果的に初回起動が早い
あえて言うならば
コンパクトなアートリソース
- 40. Copyright © 2015 Wright Flyer Studios, Inc. All Right Reserved.
• やっぱりUIとロジックは切り離したい
• 手書きは慣れると早いけど
• オススメはしない
• 大規模な画面仕様の変更がはいると
• QAを厚くしないと不安で寝れない
• エンジニアが全員職人なわけがない
• アニメーションは書かないと感覚が身につかない
反省点
- 42. Copyright © 2015 Wright Flyer Studios, Inc. All Right Reserved.
• Cocos2d-x 3.2に積んでるlibcurlが古い
• HTTP Status : 200なのにresponseが空っぽ
• オプションによってはタイムアウト時にクラッシュ
• libcurlの乗り換え検討中
• SQLiteのWriteが遅い
• Write前にReadしてハッシュ比較
• 探検中データの下位互換
• Nヶ月前のダンジョン内のデータをちゃんと救えるかどうか
• どうしてもダメになるまでは諦めないけどやはり辛い
苦労したところ
- 44. Copyright © 2015 Wright Flyer Studios, Inc. All Right Reserved.
• 今後ともタワーライジングを宜しくお願いします!
• もうすぐ自分の塔33階まで解放します!
おわりに
- 45. Copyright © 2015 Wright Flyer Studios, Inc. All Right Reserved.
Happy Hacking♥