Roll It を作成しています

Roll It は、スマートフォンとパソコンのブラウザだけで、クラシックなボードウォーク ゲームを一新する Chrome 試験運用版です。スマートフォンのブラウザでは、手首を振るだけでボールを振り回すことができます。一方、パソコンのブラウザでは、WebGL と Canvas を使用して、Roll It アレイのグラフィックがリアルタイムでレンダリングされます。2 つのデバイスは WebSocket 経由で通信します。アプリはありません。ダウンロードはありません。トークンがありません。必要なのは最新のブラウザだけです。

Legwork は Google Creative Lab の指示のもと、ユーザー エクスペリエンス、インターフェース、ゲーム環境を開発し、開発パートナーの Mode Set と協力して Roll It を構築しました。プロジェクトの期間中、いくつかの固有の課題がありました。この記事では、Roll It を実現するためのテクニック、発見したコツ、学んだ教訓を紹介します。

3D ワークフロー

当初の苦労の 1 つは、3D モデルを当社のソフトウェアからウェブ対応のファイル形式に変える最良の方法を見つけることでした。Cinema 4D でアセットを作成した後、モデルは簡素化され、低ポリゴン メッシュに変換されました。色やテクスチャのためにオブジェクトの各部分を区別するために、各メッシュに特定のポリゴン選択タグが割り当てられました。その後、3D と互換性のあるファイルを作成するために、Collada 1.5(.dae)ファイルとしてエクスポートし、オープンソースの 3D プログラムである Blender にインポートしました。モデルが正しくインポートされたことを確認したら、メッシュを JSON ファイルとしてエクスポートし、コードを使用してライティングを適用しました。実施した手順の詳細は次のとおりです。

C4D 内でオブジェクトをモデル化します。メッシュの法線が外側を向いていることを確認します。
C4D 内でオブジェクトをモデル化します。メッシュの法線が外側を向いていることを確認します。
ポリゴン選択ツールを使用して、テクスチャを適用する特定の領域の選択タグを作成します。各選択タグにマテリアルを適用します。
ポリゴン選択ツールを使用して、テクスチャを適用する特定の領域の選択タグを作成します。各選択タグにマテリアルを適用します。
メッシュを COLLADA 1.5 .dae ファイルとしてエクスポートします。
メッシュを COLLADA 1.5 .dae ファイルとしてエクスポートします。
[2D ジオメトリをエクスポートする] チェックボックスがオンになっていることを確認します。一般に、三角形のエクスポートは 3D 環境でコード側の対応が広くなりますが、ポリゴンの数が 2 倍になるというデメリットがあります。ポリゴンの数が多いほど、コンピュータのプロセッサに対するモデルの負荷が高くなります。そのため、パフォーマンスの低下が見られる場合は、このチェックボックスをオフのままにしてください。
[2D ジオメトリをエクスポートする] チェックボックスがオンになっていることを確認します。一般に、三角形のエクスポートは 3D 環境でコード側の対応が広くなりますが、ポリゴンの数が 2 倍になるというデメリットがあります。ポリゴンの数が多いほど、コンピュータのプロセッサに対するモデルの負荷が高くなります。パフォーマンスの低下が見られる場合は、チェックボックスをオフのままにしてください。
Collada ファイルを Blender にインポートします。
Collada ファイルを Blender にインポートします。
ミキサーにインポートされると、素材と選択タグも引き継がれています。
Brainer にインポートされると、素材と選択タグも引き継がれていることがわかります。
オブジェクトを選択し、オブジェクトのマテリアルを好みに合わせて調整します。
オブジェクトを選択し、オブジェクトのマテリアルを好みに合わせて調整します。
ファイルを split.js ファイルとしてエクスポートします
webGL との互換性を確保するために、このファイルを 3.js ファイルとしてエクスポートします。

コードの記述

Roll It はオープンソース ライブラリで開発されており、最新のブラウザでネイティブに動作します。WebGL や WebSocket などのテクノロジーにより、ウェブはコンソール品質のゲームやマルチメディア エクスペリエンスに近づきつつあります。HTML 開発用の最新のツールが利用可能になるにつれ、デベロッパーがこうしたエクスペリエンスを簡単に構築できる点は飛躍的に向上しています。

開発環境

Roll It の元のコードのほとんどは、CoffeeScript で記述されています。CoffeeScript は、適切な形式の lint チェックの JavaScript にトランスコンパイルできる、クリーンで簡潔な言語です。CoffeeScript は、優れた継承モデルとよりクリーンなスコープ処理により、OOP の開発に効果を発揮します。CSS は SASS フレームワークで作成されており、プロジェクトのスタイルシートを拡張、管理するための優れたツールをデベロッパーが数多く提供しています。これらのシステムをビルドプロセスに追加すると、セットアップに少し時間がかかりますが、特に Roll It のような大規模なプロジェクトでは、その見返りは間違いなくその価値があります。開発中にアセットを自動コンパイルするために Ruby on Rails サーバーをセットアップしたので、これらのコンパイル手順がすべて透過的になりました。

効率的で快適なコーディング環境を構築するだけでなく、サイトの読み込み時間を短縮するために、アセットを手動で最適化してリクエストを最小限に抑えました。すべての画像に、ImageOptimImageAlpha のいくつかの圧縮プログラムを使用しました。各プログラムは、それぞれ独自の方法(可逆圧縮と非可逆圧縮)で画像を最適化します。設定を適切に組み合わせることで、画像のファイルサイズを大幅に削減できます。これにより、外部画像を読み込む際の帯域幅が節約されるだけでなく、最適化されると、HTML、CSS、JavaScript にインラインで埋め込めるように、画像がはるかに小さい base64 エンコード文字列に変換されます。base64 エンコードを主題にしていますが、この手法を使用して Open Sans WOFF フォント ファイルと SVG フォント ファイルを CSS に直接埋め込んだため、合計リクエスト数はさらに減少しました。

物理学に対応した 3D シーン

THREE.js は、ウェブで広く使用されている 3D JavaScript ライブラリです。ローレベルの 3D 数学とハードウェア ベースの WebGL 最適化機能がまとめられています。これにより、カスタム シェーダーを作成したり、手動でマトリックス変換を実行したりすることなく、単にモータルが明るく美しいインタラクティブな 3D シーンを簡単に作成できるようになります。Physijs は、一般的な C++ 物理ライブラリの THREE.js 固有のラッパーで、JavaScript に変換されています。このライブラリを利用して、ボールの転がり、ジャンプ、跳ね返りを目的地に向かって 3D でシミュレートしました。

当初から、ボールを転がす物理的な体験をリアルに感じられるだけでなく、ゲーム内のオブジェクトがリアルに感じられるようにすることに着手しました。そのためには、Physijs シーンの全体的な重力、プレーヤーのスローから転がる際のボールの速度、レーンのジャンプの傾き、ボールとレーンのマテリアルの摩擦と反発(弾力)特性の調整を何度も繰り返す必要がありました。重力とスピードの組み合わせにより、よりリアルなゲーム体験が実現しました。

平滑化

最新のブラウザとビデオカードの組み合わせでは、WebGL 環境のネイティブ ハードウェア ベースのアンチエイリアスを活用する必要がありますが、一部は適切に再生できません。アンチ エイリアスがネイティブに動作しない場合、THREE.js シーンの硬くコントラストの強いエッジはギザギザになり、(少なくとも、人間の目には)見づらくなります。

幸いなことに、コード スニペットから、プラットフォームがアンチエイリアスをネイティブにサポートしているかどうかを検出できます。サポートしているのであれば、問題ありません。そうでなければ、THREE.js に付属する一連の後処理シェーダーが役立ちます。FXAA アンチエイリアス フィルタです。このシェーダーを使用して、レンダリングされたシーンをフレームごとに再描画すると、通常は線とエッジがはるかに滑らかになります。以下のデモをご覧ください。

// Check for native platform antialias support via the THREE renderer
// from: http://codeflow.org/entries/2013/feb/22/how-to-write-portable-webgl/#antialiasing
var nativeAntialiasSupport = (renderer.context.getParameter(renderer.context.SAMPLES) == 0) ? false : true;

加速度計ベースのゲーム コントロール

Roll It のマジックは、プレーヤーがスマートフォンを使ってボールを回転させるジェスチャーを主な要素としています。以前から、モバイル デバイスではブラウザ内の加速度計が利用されてきましたが、業界としては、動きベースのジェスチャー認識をウェブ上で検討し始めたばかりです。スマートフォンの加速度計が提供するデータによって多少は制限されますが、ちょっとした工夫次第で、新しい素晴らしいエクスペリエンスを生み出すことができます。

Roll It の主な「ロール」操作は、ウィンドウの deviceorientation イベントによる最新の 10 件の加速度計の更新をトラッキングすることから始まります。現在の傾斜値から以前の傾斜値を差し引くと、イベント間の角度の差分が保存されます。そして、最後の 10 個の角度デルタを常に合計することで、スマートフォンが空間内を移動する際の連続的な回転を検出できます。スマートフォンがスイープする角度の変化のしきい値を超えると、ロールがトリガーされます。そのスイープ内で最大の単一傾斜デルタを見つけることで、ボールの速度を推定できます。Roll It では、この速度は各加速度計の更新に付加されたタイムスタンプを使用して正規化されます。これにより、加速度計の更新がさまざまなデバイスのブラウザにストリーミングされる際の速度の変動がスムーズになります。

WebSocket 通信

プレーヤーがスマートフォンでボールを転がすと、スマートフォンからノートパソコンにボールを発射するよう求めるメッセージが送信されます。この「ロール」メッセージは、2 台のマシン間の WebSocket 接続を介して、JSON データ オブジェクトを介して送信されます。JSON データは小さく、主にメッセージ タイプ、投げる速度、照準の方向で構成されます。

{
  "type": "device:ball-thrown",
  "speed": 0.5,
  "aim": 0.1
}

ノートパソコンとスマートフォンのすべての通信は、このような小さな JSON メッセージを介して行われます。デスクトップでゲームの状態が更新されるたび、またはユーザーがスマートフォンのボタンをチルトまたはタップするたびに、WebSocket メッセージがマシン間で送信されます。この通信をシンプルかつ管理しやすいようにするため、WebSocket メッセージはいずれかのブラウザから単一の終了ポイントを使用してブロードキャストされます。逆に、受信側ブラウザには単一のエントリ ポイントがあり、1 つの WebSocket オブジェクトが両端ですべての送受信メッセージを処理します。WebSocket メッセージを受信すると、JSON データは jQuery の trigger() メソッドを使用して JavaScript アプリ内で再ブロードキャストされます。この時点で、受信データは他のカスタム DOM イベントと同じように動作し、アプリケーション内の他の任意のオブジェクトで取得して処理できます。

var websocket = new WebSocket(serverIPAddress);

// rebroadcast incoming WebSocket messages with a global event via jQuery
websocket.onmessage = function(e) {
  if (e.data) {
    var obj = JSON.parse(e.data);
    $(document).trigger(data.type, obj);
  }
};

// broadcast outgoing WebSocket messages by passing in a native .js object
var broadcast = function(obj) {
  websocket.send(JSON.stringify(obj));
};

Roll It の WebSocket サーバーは、2 つのデバイスがゲームコードと同期されるとオンザフライで作成されます。Roll It のバックエンドは、Go を使用して Google Compute EngineApp Engine プラットフォームで構築されました。

メニュー画面の傾斜

Roll It のメニューは、ゲームプレイ中に使用されるイベント ドリブンの WebSocket メッセージ以外にも、スマートフォンを傾けて選択を確定するためのボタンをタップすることで制御されます。そのためには、スマートフォンからノートパソコンに送信されるチルトデータのストリームに、一貫性を持たせる必要があります。帯域幅を減らし、不要な更新の送信を回避するために、これらのメッセージはデバイスの傾斜が数度以上変化した場合にのみ送信されます。スマートフォンをテーブルの上に平らに置いているなら、傾斜データのストリームを送信しても意味がありません。転送レートもスロットリングされます。デバイスがアクティブに傾いていても、Roll It では 1 秒あたり 15 件以下の WebSocket メッセージしか送信されません。

傾斜の値がコンピュータ上で取得されると、requestAnimationFrame を使用して徐々に補間され、滑らかな感触が保たれます。最終的には、ユーザーの選択を示すために回転するメニューとボールが回転します。スマートフォンが傾斜データを送信すると、requestAnimationFrame ループ内で CSS 変換を再計算して、これらの DOM 要素がリアルタイムで更新されます。メニューのコンテナは単純に回転しますが、ボールは床に沿って転がっているように見えます。この効果を実現するため、基本的な三角法を実装して、ボールの x 座標をその回転に関連付けます。簡単な方程式: 回転 = x / (直径 * pi)

まとめ

サイコロを振って開発の原動力となったオープンソース プロジェクト、Google のデスクやポケットにあるデバイスの処理能力、プラットフォームとしてのウェブの状態。オープンウェブでつながるのは本当にエキサイティングで変革的な時です。つい数年前までは、この技術の多くは独自仕様のシステムだけで存在し、自由に使用、配布することはできませんでした。今では、毎日新しいパズルのピースを作成して共有していく中で、複雑なエクスペリエンスをより少ない労力と想像力で実現できます。ぜひご自身で Pinpoint を魅力的なアプリを作成して、世界中のユーザーと共有しましょう。

Roll It ロゴ