こんにちは、KIRAKIRAKINGYOディベロップチーム(オオシモ、カワバタ、鈴木、バンバ)です。

今回は、KIRAKIRAKINGYOの開発の裏側をお伝えしたいと思います。(デザイン編はこちら

写真は、京都行きの新幹線での最後の追い込み風景です。

仕組み

まず、デバイスとFLASHとがリアルタイムに通信する必要があるので、nodejsでサーバーを構築しました。wsというモジュールを用いてWebSocket通信をしています。(nodejsについてはこちら:フロントエンドエンジニアにおけるNode.jsのススメ)また、サーバーにはプレイヤーのスコア/ランキング情報をデータベースに保持する役割も持たせました。

図は、デバイス・FLASH間のデータのやりとりのフローを表しています。


  1. デバイスからポイの回転/位置情報を、リアルタイムでFLASHにサーバーを介して送ります。
  2. FLASHは受け取ったデバイス情報を元に当たり判定を行います。そして、釣った金魚/残機の情報をリアルタイムでサーバーを介してデバイスに送ります。
  3. 最後にプレイヤーのスコアをデータベースに保存し、ランキングを表示します。


実際に使用した機器は以下のようになっています:

  • デバイス:iPhone 5C
  • サーバー:MacBook Air
  • ディスプレイ:テレビ(MacBook Proの画面をミラーリング)

デバイスの裏側

センシング

当初はフルネイティブ(Objective-C)での実装を予定していました。しかし今回用いたiPhone 5C(iOS4.2以上)であると、JavaScriptでデバイスのセンサー情報を取得できることを知り、JavaScriptでの開発にシフトしました。


devicemotion

デバイスの重力加速度の値を用いてポイを移動させています。さらに、重力加速度の変位からポイをすくった動作を判定しています。

デモ(iOS4.2以上、Android3.0以上で動作します)


deviceorientation

デバイスの回転情報を電子コンパスから取得します

デモ(iOS4.2以上、Android3.0以上で動作します)


個人的に勉強のためにObjective-Cを使いたかったので、webviewをアプリでラップしています。アプリにすることでフルスクリーンに出来たり、スリープモードにならないように出来たり役に立ちました。

画面遷移

画面の遷移/DOM操作にはchikuwa.js(詳しくは:スマートフォン向けJavaScriptライブラリchikuwa.js)を用いています。

画面の構成は以下になっています


#top

プレイヤーネームを入れる画面です。

#play

プレイ画面です。釣った魚が画面下部に表示されます。

#score

スコアを表示します。

#ranking

ランキングを表示します。

#maintenence(隠し)

デバイスの角度の取得に誤差が生じるため、メンテナンスモードというのを密かに搭載しています。メンテナンスモードでは、対象のポイの角度を外部から変更することが出来ます。また、たまにwebviewが落ちてしまう現象がありました。(おそらく通信に耐えれなくなって落ちてしまう)そのため、途中で落ちたポイを消すモードもメンテナンスモードに含まれています。

iPhoneで対象物との距離は取れるのか?

今回デバイスの傾きによってポイを動かす方法にしましたが、デバイスとディスプレイとの距離を測る方法も調査しました。


StickNFind Stickers

StickNFind Stickersは、Bluetoothを内蔵したボタン型の端末です。SDKも公開されており、デバイスとのBluetothの強度によって距離を出すことは出来ますが。誤差や距離を計算するまでにラグがあるために採用になりませんでした。


慣性航法

飛行機やミサイルなどにも採用されている方法で、デバイスがどのくらい動いたかを加速度を2回積分して算出する方法です。これも誤差が大きく採用にはなりませんでした。


本来は、腕の動きに合わせてポイが動いたほうがより金魚すくいっぽくなったと思います。次回チャンスがあるとすれば画像認識を使って腕の動きを検出することに挑戦してみたいと思います。

FLASHの裏側

水槽の中を再現するには?

金魚すくいを実現するために、なんといってもあの「金魚が群れで動く様子」をちゃんと再現する必要があります。金魚が水槽の中を時には群れたり、時にはランダムで動いたりする様を見て、お祭りの時にワクワクしたものです。そのワクワクをゲームでも再現したい!というのがこのゲームの出発点でもあります。群れを再現するためには、魚の動きをランダムで動かすだけではだめで、かと言ってかたまりで動かしてもだめです。「それぞれの魚が個別に動いている」かつ「群れとして動いてる」状態を再現しなければなりません。


今回、その魚の群れの動きの再現のためにBoidアルゴリズムを使用しました。Boidアルゴリズムとは、「結合」「整列」「分離」3つのルールを設けるだけで鳥の群集をシミュレーションできるという理論です。ゲームのパーティクルの動きなんかはこういった群集シミュレーションの理論が用いられて作られている事が多く、奥が深い分野なので、興味のある方は調べてみてください。

Boidアルゴリズム3つのルール

「結合」:群れの中心に向かっていく

魚が多く集まっている方に向かっていくルールです


「整列」:同じ方向を向いて動く

違う方向を向いていれば、同じ方向を向いて動いていくルールです。


「分離」:近づき過ぎたら離れていく

衝突を避けるように離れていくルールです。


以上の3つのシンプルなルールだけで魚の群れのような動きを再現することができます。 

魚それぞれが互いに影響し合い、上記のルールに沿って毎フレーム動いていきます。

魚は全部で6種類あるんですが、それぞれの種類ごとに上記3つのルールのパラメータに変化を付けています。

「小さい魚は群れやすく、大きい魚は群れにくい」といったパラメータの調整を入れて、魚の群れ感を出しています。


リアルな金魚すくいでも、ポイで金魚をすくおうとした時、ポイから金魚が逃げていって捕まえられなかったことあると思います。

ポイから魚が逃げていく処理も入れて、リアルな金魚すくい感を出しています。


完成した魚の群れの動きの動画はこちら:


今回は、ブラウザで動かす必要がないので、アプリケーションの構成はairアプリにパッケージングして使用しました。

デバイスとユーザビリティ

スマホの傾きのデータを受け取って、その値を元にポイを上下左右に動かしています。

上下左右の動きだけでなく、ポイの回転も考慮に入れないといけません。

ユーザーがどの位置に立ってもゲームをプレイできるように、ポイが常にユーザーの方に向く処理が必要です。

スマホで電子コンパス(方位磁針)のデータを受け取ることができるので、今スマホがどの方角を向いているのかを取得できます。

そのスマホのデジタルコンパスの値を受け取って、その値を元にポイを回転させて、ポイが常にユーザーの方に向くようにしてユーザビリティの向上に努めました。



アニメーション

ポイのアクション(魚をすくう、ミスして破れる)と水面に波紋が広がるエフェクトをタイムラインアニメーションで作成しました。

他にも細かい小さなアニメーションを色々作成したのですが、3つにしぼって紹介します。

こういったアニメーションがタイムラインで効率的かつ表現力豊かに編集できるのがFlashの醍醐味です。

ポイのアクション

   


ミスとスコアのテキストアニメーション

魚をすくうのに失敗した時、成功した時のアニメーションです。


水面の波紋アニメーション

魚をすくった時や魚が反転した時に出るようにしています。

出来なかったこと

今回、チャレンジの一つとして、stage3Dの使用を当初考えていたんですが、2Dゲームということもあり必要性もなく(自分自身の余裕もなく)断念してしまいました。stage3DとはFlash Player 11で新しく追加された機能で、Flashにおける3Dレンダリングの速度を向上させる機能です。GPUに直接アクセスしてグラフィック処理を行うので、通常の描画速度よりもはるかに速くレンダリングが可能です。3D描画だけでなく、画像処理も高速でできるので、水面がゆらゆら揺れるエフェクトなどをstage3Dで実装してリッチな表現に挑戦したかったです。stage3Dについて、詳しくはこちらの記事を御覧ください。


役割分担

Flashの開発は2名で分担して行いました。主な作業は次の3つで、これらを分担して行いました。


ゲームのフレームワークの大枠を作る

全体の画面遷移部分と通信やリソース(画像など)の読み込みのタイミングを加味して、まずは全体の大枠のフレームワークを設計します。
弊社のサービスであるアメーバピグでも使用している、各モジュールがMVCを持ち更にそれらを取りまとめるメインのMVCがあるというフレームワークを参考にして作っています。そうすることでモジュール単位で開発ができるようなるので、各モジュールのみでのテストや開発の分担がしやすくなります。
今回はトップ画面とゲーム画面と通信を別々のモジュールで作成しています。


ゲームロジック

ゲームの内容を決める重要な部分なので、構造だけでなくゲームとしての演出と操作感などを加味した設計にしなければなりません。

  • 魚の動き
  • ポイの操作感
  • すくう時の当たり判定

など、実装するべきところはゲームの根幹に関わる所なので重要です。

モックを作る→他の人にプレイしてもらい、フィードバックをもらう→プログラムに反映

このサイクルをどんどんやっていくことでクオリティの高いゲームができあがります。

テストプレイ中にその場で、「魚の動きもっと速くできない?」「魚の数を増やしたい」といった要望にも即座に対応できるように、パラメータはリアルタイムに操作できるようにスライダを作成して、その場で魚の動きなどを微調整できるようにしておきました。こういった現場での微調整はインスタレーションにはつきものなので、あらゆる場面を想定した設計がゲームプログラマには必要です。

まとめ

普段はWebサービスを運用/開発しているので、実際にシステムを触って楽しんでいる姿を見ることが出来る貴重な機会となりました。そのような姿を見ることは、とても嬉しいし、開発へのモチベーションを維持することにつながると感じました。

そして事業的な縛りなしに、純粋にオモシロイもの/新しい技術を追求する姿勢は、普段の業務にも取り入れていきたいと思います。