Slide 1

Slide 1 text

Copyright © 2015 Wright Flyer Studios, Inc. All Right Reserved. Wright Flyer Studios部 西田綾佑 Cocos2d-xを用いた "LINE タワーライジング" の開発事例 GREE GameDevelopers' Meetup 01 #greegdm01

Slide 2

Slide 2 text

Copyright © 2015 Wright Flyer Studios, Inc. All Right Reserved. • 西田綾佑 (にしだ りょうすけ) • グリー株式会社 Wright Flyer Studio部 • クライアントリード(エンジニア) • @hosi_mo • 塔コード : 4M9EVCBK • 経歴 • 東京大学大学院情報理工学系研究科 修了 • グリー株式会社(2014年~) 自己紹介

Slide 3

Slide 3 text

Copyright © 2015 Wright Flyer Studios, Inc. All Right Reserved. ゲーム紹介 配信日 : 2015/6/23 ジャンル : RPG、アドベンチャー プラットフォーム : iOS / Android おかげさまで事前登録43万人 ▼塔はつんでも、人生つむな ▼頭脳系ダンジョンRPG ▼方向音痴の作者が作った、 新しいスタイルのダンジョン探検

Slide 4

Slide 4 text

Copyright © 2015 Wright Flyer Studios, Inc. All Right Reserved. 実はDungeon Flickerがベースとなった

Slide 5

Slide 5 text

Copyright © 2015 Wright Flyer Studios, Inc. All Right Reserved. “タワーライジング” リリースまでの開発体制 プロデューサー 1名 クライアントプログラマ 4名 サーバプログラマ 3名 アート 2名 ディレクター(原作) 1名 ゲームデザイナー 2名 PM 3名 16名

Slide 6

Slide 6 text

Copyright © 2015 Wright Flyer Studios, Inc. All Right Reserved. 全体スケジュール(14ヶ月) 2015年 3月~ ダンジョンフリッカー公開 2014年 4月~ α開発 10月~ β開発 β開発 ~1月 1月~ LINE連携 4~6月 チュートリアル改善 6月 GA 社内リリース 社内リリース 11月〜ベンダーテスト ベンダーテスト ~4月

Slide 7

Slide 7 text

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を眺めてスレッドを感じる 開発環境

Slide 8

Slide 8 text

Copyright © 2015 Wright Flyer Studios, Inc. All Right Reserved. • libdispatch • 並列化したい処理だけキューに投げられて便利 • Cricket Audio • サウンドの再生。安定してる。 • 他プロジェクト(Cocos2d-x)で実績あり • Jenkins • 毎日自動でビルドを作って社内チャットに共有 • Hockey App • ビルド配布 • クラッシュログ収集 要素技術

Slide 9

Slide 9 text

Copyright © 2015 Wright Flyer Studios, Inc. All Right Reserved. タワーライジングの開発

Slide 10

Slide 10 text

Copyright © 2015 Wright Flyer Studios, Inc. All Right Reserved. • Cocos2d-xで作り直したい • ダンジョンフリッカーはAdobe Air • 画面数が少ない • 複雑な画面が少ない • 社内ツール : レイアウトローダ(psd -> Cocos2d-x) を使うほどでもない • 簡素な演出が好まれた • LWFを使うほどではない • 当時 : (送りバントと呼ばれたプロジェクト) • そもそものアサインが少ない(さらにFlashアニメータ自体が社内に少ない) 開発初期(2014年春~夏) 2014年3月にダンジョンフリッカーをリリース

Slide 11

Slide 11 text

Copyright © 2015 Wright Flyer Studios, Inc. All Right Reserved. • UI配置 : エンジニアが頑張る • UIアニメーション : エンジニアが頑張る • 演出 : エンジニアが頑張る 結果 oh. . . .

Slide 12

Slide 12 text

Copyright © 2015 Wright Flyer Studios, Inc. All Right Reserved. アサインされたエンジニアが面食らう

Slide 13

Slide 13 text

Copyright © 2015 Wright Flyer Studios, Inc. All Right Reserved. UI配置 おわかりいただけるだろうか?

Slide 14

Slide 14 text

Copyright © 2015 Wright Flyer Studios, Inc. All Right Reserved. タワーライジングは町工場だから

Slide 15

Slide 15 text

Copyright © 2015 Wright Flyer Studios, Inc. All Right Reserved. • UI • コードに座標打ってもなんとかなる..かも? • 演出 • runAction()も、Easingもあるじゃないか • パペットアニメーションの実現は… 開発初期 エンジニアから職人へのジョブチェンジ

Slide 16

Slide 16 text

Copyright © 2015 Wright Flyer Studios, Inc. All Right Reserved. アニメーション 安心してください、書いてますよ Avatar.cpp 1200行くらい

Slide 17

Slide 17 text

Copyright © 2015 Wright Flyer Studios, Inc. All Right Reserved. なんとかなった理由 ①画面がシンプル

Slide 18

Slide 18 text

Copyright © 2015 Wright Flyer Studios, Inc. All Right Reserved. なぜその① 画面の仕様がシンプル

Slide 19

Slide 19 text

Copyright © 2015 Wright Flyer Studios, Inc. All Right Reserved. なぜその① 画面の仕様がシンプル • すべての画面を同一のコンポーネントでつくる • アニメーションが共通化できる • SEが共通化できる • 基本的に9sliceで作りきれる範囲の装飾

Slide 20

Slide 20 text

Copyright © 2015 Wright Flyer Studios, Inc. All Right Reserved. なんとかなった理由 ②仕様書もシンプル

Slide 21

Slide 21 text

Copyright © 2015 Wright Flyer Studios, Inc. All Right Reserved. なぜその② 一枚絵とにらめっこして作り上げられる • 仕様書が画像一枚(+注釈) • 位置もこれがマスター 究極的には エンジニアがこの一枚絵を完コピすれば良い

Slide 22

Slide 22 text

Copyright © 2015 Wright Flyer Studios, Inc. All Right Reserved. なんとかなった理由 ③Flashで動いている

Slide 23

Slide 23 text

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++

Slide 24

Slide 24 text

Copyright © 2015 Wright Flyer Studios, Inc. All Right Reserved. なんとかなった理由 ④消滅都市先輩がいた

Slide 25

Slide 25 text

Copyright © 2015 Wright Flyer Studios, Inc. All Right Reserved. • クライアントサイド • 通信 • データベース • サーバーサイド • 概ね消滅都市と同等の構成(Silex + MagicSpice) なぜその④ 消滅都市から基本機能を切り出して改良した エンジニアリングにおける挑戦をしなかった 安全な方向に倒す開発に専念した その他プロジェクトの偵察を怠らなかった

Slide 26

Slide 26 text

Copyright © 2015 Wright Flyer Studios, Inc. All Right Reserved. 設計のはなし

Slide 27

Slide 27 text

Copyright © 2015 Wright Flyer Studios, Inc. All Right Reserved. • TitleScene • ログイン処理、データベース構築など • HomeScene • ホーム画面 (塔を俯瞰したあの画面) • DungeonScene • ダンジョン内 • DecorationScene • デコレーションする画面 全体の設計 シーン一覧

Slide 28

Slide 28 text

Copyright © 2015 Wright Flyer Studios, Inc. All Right Reserved. ステートの分割 UIの動きに見合うステートマシンもどきを設計した • Layerの管理 • Stack型の状態管理(ゲームロジック) • Viewのトランジションも自動化 LayerのPush()とPop()で階層的なUIを管理 StateManager::getInstance()->pushState(レイヤー); StateManager::getInstance()->popState();

Slide 29

Slide 29 text

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); } });

Slide 30

Slide 30 text

Copyright © 2015 Wright Flyer Studios, Inc. All Right Reserved. • 階層的な画面が容易に作れた • ウィンドウの表示・非表示のアニメー ションが楽に統一化できた • UIベタ書きでもなんとか持ちこたえた 階層的なUIの実現 そのおかげで

Slide 31

Slide 31 text

Copyright © 2015 Wright Flyer Studios, Inc. All Right Reserved. 特徴的な機能の実装例

Slide 32

Slide 32 text

Copyright © 2015 Wright Flyer Studios, Inc. All Right Reserved. • 地道に1フリックごとに状態を保存 • バトル中は特定のタイミングでス ナップショットをとっている • ※暗号化しています オートセーブ機能 ダンジョン内にいる場合いつでもアプリをkillできる

Slide 33

Slide 33 text

Copyright © 2015 Wright Flyer Studios, Inc. All Right Reserved. • グレースケールで書かれたレンガに 画像を乗算してalpha指定 • 横の壁はSpriteを3軸で歪ませて表現 • レンガのパースが厳密でないので鬼の位置調整 デコレーション 乗算でそれっぽく仕上げる BlendFunc blend; blend.src = GL_ZERO; blend.dst = GL_SRC_COLOR;

Slide 34

Slide 34 text

Copyright © 2015 Wright Flyer Studios, Inc. All Right Reserved. • iOS • Obj-C • UIImageで頑張る • Android • Java • Bitmap.createBitmapで頑張る 顔はめ込み機能 両OSでNative Bridge先で端末内の画像をcropする

Slide 35

Slide 35 text

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");

Slide 36

Slide 36 text

Copyright © 2015 Wright Flyer Studios, Inc. All Right Reserved. パフォーマンス

Slide 37

Slide 37 text

Copyright © 2015 Wright Flyer Studios, Inc. All Right Reserved. • アクションゲームではない • 30FPSで問題ない • 演出が激しくない • 要求されるものがすくない • がんばらなくてよかった パフォーマンス

Slide 38

Slide 38 text

Copyright © 2015 Wright Flyer Studios, Inc. All Right Reserved. • アイテム画像全部で500KBくらい • アートさんがモンスターも1枚1枚減色してくれた • アセットダウンロード無しで初期リリースを決意 • 結果的に初回起動が早い あえて言うならば コンパクトなアートリソース

Slide 39

Slide 39 text

Copyright © 2015 Wright Flyer Studios, Inc. All Right Reserved. 反省

Slide 40

Slide 40 text

Copyright © 2015 Wright Flyer Studios, Inc. All Right Reserved. • やっぱりUIとロジックは切り離したい • 手書きは慣れると早いけど • オススメはしない • 大規模な画面仕様の変更がはいると • QAを厚くしないと不安で寝れない • エンジニアが全員職人なわけがない • アニメーションは書かないと感覚が身につかない 反省点

Slide 41

Slide 41 text

Copyright © 2015 Wright Flyer Studios, Inc. All Right Reserved. 苦労したところ

Slide 42

Slide 42 text

Copyright © 2015 Wright Flyer Studios, Inc. All Right Reserved. • Cocos2d-x 3.2に積んでるlibcurlが古い • HTTP Status : 200なのにresponseが空っぽ • オプションによってはタイムアウト時にクラッシュ • libcurlの乗り換え検討中 • SQLiteのWriteが遅い • Write前にReadしてハッシュ比較 • 探検中データの下位互換 • Nヶ月前のダンジョン内のデータをちゃんと救えるかどうか • どうしてもダメになるまでは諦めないけどやはり辛い 苦労したところ

Slide 43

Slide 43 text

Copyright © 2015 Wright Flyer Studios, Inc. All Right Reserved. おわりに

Slide 44

Slide 44 text

Copyright © 2015 Wright Flyer Studios, Inc. All Right Reserved. • 今後ともタワーライジングを宜しくお願いします! • もうすぐ自分の塔33階まで解放します! おわりに

Slide 45

Slide 45 text

Copyright © 2015 Wright Flyer Studios, Inc. All Right Reserved. Happy Hacking♥