はじめまして、こんにちは。
アメーバ事業本部ゲーム部門コア室という所で、ディベロッパーをしております、佐藤圭明と申します。

前回の「ガールフレンド(仮)」の秋山さんのお話につづき、アメーバ内製タイトルのヒット作である、「天下統一クロニクル(※以下「天クロ」と表記)を元にお話しさせて頂きたいと思います。

「天クロ」では、アニメーションの制作にFlash CS6とToolkit For CreateJS(※以下、「TFC」と表記)を使用しており、ゲーム内のイベントに合わせて月に3、4本くらい作っているイメージです。また、その他の内製タイトルでは、「天空のクリスタリア」「不良魂 ~全国制覇~ 」「ガールフレンド(仮)」「ぼくらのブレイブガーディアン」でもTFCを使用しております。

ゲーム自体は2012年の4月末から開発がスタートし、9月の頭にリリースとなりました。開発時からリリース後の運用に至るまで、アニメーションについても様々な問題と直面しながら、解決に至ってきたわけですが、そんな中でみつけた具体的なお話を今回はさせて頂ければと思います。

アニメーションの制作フローについて

まずは、イベントのオープニングアニメーションの制作フローを元に、具体的な作業を説明したいと思います。
フロー図フロー図
※「マージ」とは、出来上がったHTMLやJSファイルをシステムと結合する作業の事です。
この工程の中で、私が担当するのは3から5の部分となります。もちろん、1のブレストにも参加して、実現可能な表現かどうかという話もしています。

それでは、担当する工程の詳細をお話ししていきます。


受け取ったデータを元にスプライト画像を作成

使用する画像は、PNG中心で解像度も高いため、重いデータになりがちなのですが、スマフォの回線はまだまだ貧弱です。アニメーションでは3G回線を考慮して、devicePixelRatio=1の画像を使用し、devicePixelRatioが1.5や2の実機上では拡大されたものが再生されております。

また、リクエスト数を減らすために、スプライト画像を使うのはごく当たり前の事ですので、受け取ったPSDを元に透過有り(png)と透過無し(jpg)の2枚のスプライト画像を作成して、ページ全体のリクエスト数を10本程度まで抑えております。

透過有りスプライト透過有りスプライトスプライト画像が完成したら、透過有りの画像をデザイナーさんに減色処理してもらいます。これにより容量が3分の1ほどまで減り、見た目的にはそれほど劣化しません。その後、ImageOptimなどで不要なメタデータの削除なども行い、出来るだけ計量化します。


Flash上でオーサリングしてアニメーションを作成

ここのフローは通常のFlashでのアニメーション作成手順とほぼ同様ですが、いくつか気を付ける点があります。

●スプライト画像から各パーツを作成
素材は1枚、もしくは2枚の画像に入っているので、これらの画像を配置したMovieClipを作成し、必要な部分だけが表示されるようにマスクを追加して行きます。
※Flash CS6には、スプライトシートの書き出し機能もあるので、もっと楽なフローが作れそうです。

マスクでスプライトマスクでスプライト


●動くパーツはMovieClipで作成する
swf作成時と同様、動かすものはMovieClipで作成します。グラフィックシンボルを使って動かした場合は、tweenオブジェクトが追加されるため、書き出されるコードが若干増えます。動かすオブジェクトが増えれば増えるほど、一緒に増えてしまうので、必ずMovieClipで作成しましょう。

ライブラリライブラリ

●ラベル名に気を付ける
swfでの書き出しを想定した場合は、あまり気にしなくて良かった事ですが、TFCで書き出す場合、ラベル名はそのままObjectのkeyとして使われます。

うっかりJSの予約語を使っていて、一度問題が出てしまった事がありますので、分かりやすい名前にする事はもちろん、このコードが関わるあらゆる仕組みの中で問題が出ないよう、気つけて命名しましょう。

//MovieClipの初期化
this.initialize(mode,startPosition,loop,{tfcWLStart:0,tfcWLLoop:3},true);
※フレームラベルはinitializeの第4引数に{ラベル名:フレーム番号}の形で渡されます。


●透明ボタンは完全な透明にはしない
swfで書き出す場合は問題無いのですが、アルファが0のオブジェクトはcanvas上では存在しないものになってしまうので、1%とかに設定して完全に消えないようにする必要があります。


出力したものをサーバサイドとマージして完成

「天クロ」は、サーバサイドはJavaで作られており、FreeMarker(.ftl)というテンプレートエンジンを使っています。なので、TFCから書き出されたコードのHTMLの部分は、この.ftlファイルに埋め込む必要があります。実際には、サービスのimageファイルを置く場所を参照するように画像URLを書き換える、アニメーションをタップした際の遷移先を定義する、などの作業になります。

1つ、これ以外で重要な事で、setMaxConnections()の記述を追加する必要があります。これは、preloadJSがデフォルトで1本ずつしか画像リクエストを投げないため、ローディングに時間がかかってしまうのを解消するためです。一方で、端末側の挙動を見ていると、ブラウザ側で持っている最大接続数もあるようで、リリース後から検証を兼ねて1本ずつ増やし、現在は5を設定しています。

//同時接続数の変更
   var loader = new createjs.PreloadJS(false);
   loader.>    loader.setMaxConnections(5);//この行を追加
   loader.>    loader.loadManifest(manifest);
※initializeの第四引数に{ラベル名:フレーム番号}の形で渡されます。

以上のような手順で、イベント用のアニメーションが完成するわけですが、3から5までの工程で、大体1.5日から2日くらいで作業しております。


Androidが落ちる、止まる、ブラックアウトする、などの問題

主にはGALAXY S3で発生した問題です。シェア率の高い端末ですので、対応出来ないとかなりのインパクトとなってしまうため、ノウハウを蓄積するまでは、かなり苦労させられました。そんな中、みつけたいくつかの方法をご紹介させて頂きますので、同様の問題に遭遇したら試して頂ければと思います。

●canvasの領域外に描画しようとするとブラックアウト
canvas領域よりはみ出てしまう画像だと、canvas外に描画しようとする事があり、この場合うまく再生されずに、ブラックアウトする事があり、画面がチラついているように見える問題です。1.1から追加されたマスク機能により、canvasサイズと同サイズのシェイプでマスクするという手法で回避する事が出来ました。

●canvasアニメーションを再生しようとするとほぼ同じタイミングでブラウザが落ちる
Xperia Zという人気端末での事象です。TFCを使っている全てのゲーム、全てのアニメーションがこの問題で再生不可となってしまいました。
これは、canvasと同じサイズでclearRect()しようとするとブラウザが落ちる。というバグだったらしく、0,0座標からcanvas.widthとcanvas.heightでclearRectする処理は全てこれ以上の領域を消すように処理を変えました。結果、問題無く再生されるようになっただけでなく、S3で発生していた問題も解消され、ステージ同様のサイズでマスクする。というハックも不要になりました。TFCを使っていなくても、canvasでこの処理を行っている場合は、発生すると思います。

ちなみにこういった解決策は、社内のディベロッパー達が積極的に情報交換する事で解決されたものがほとんどであり、もし一人で開発していたらスマフォブラウザ向けサービスの開発は困難を極めることでしょう。

最後に、スマフォブラウザ向け開発について

スマートフォンブラウザ向けの開発は端末のバグや、キャリアの回線速度だったり、ネイティブアプリとのクオリティ比較だったりと、色々と苦しめられる点も多いです。そんな中でも、ベストプラクティスがなんなのか、まだ明確に定まっていない時期に、こういった仕事が出来る事はとても貴重な体験であると考えています。そんな中で、この1年間ゲーム開発を行ってきて、「技術の適材適所」を考える事が特に大事だなと、痛感いたしました。

「技術の適材適所」とは、その実装をJSでやるべきなのか、CSSでやるべきなのか、フロントエンドでやるべきなのか、サーバサイドでやるべきなのか、きっちりと考えて的確に判断する事です。これを怠ると、重すぎて動かない。動くんだけど、ブラウザが良く落ちる。電池の消耗が激しく、端末が熱くなって辛い、などなど、様々な問題が発生します。こういった問題は一つ一つが小さく見えても、積もりに積もって、いつか思わぬ問題を生むものです。

アニメーションをFlashで作っているのも、良い動きをするアニメーションをトライ&エラーしながら作るには、現状では最も良いプロセスであると考えているからです。Flashを使う事でリリースまでの工数が減らせていますし、問題が出た時の対応も即座に行えるし、何より良い動きを付ける事が出来ます。

まだまだ先の趨勢が見えないスマフォブラウザのベストプラクティスですが、常に一番良い方法が何なのか考えて正しい判断が出来るよう努力を続ける事は、作るプロとしての義務だと考えていますので、引き続き良い方法を追求していきたいと思います。