WebGLとWebSocketを使った3Dオンラインレースゲーム

R&Dの一環として、今年の夏に開催されたHTML5JapanCup2014に、JS-Racingというコンテンツを作ったのですが、よい評価を頂きまして、WebGL賞優秀賞を受賞させていただきました。

20141020_img

HTML5 Experts.jsにて、技術解説記事を寄稿させていただいています。

Chrome Experimentsでも紹介いただきました。

20141020_img7

ソースコードはすべてGitHub上に公開していますので、ご自由に閲覧ください。
knockknock-jp/js-racing.knockknock.jp

「HTML5 Experts.js」の記事とかぶりますが、せっかくなのでJS-Racingの技術解説を投稿します。以下の記事は「HTML5 Experts.js」に執筆した記事から重要なポイントのみ抜粋しています。

コンテンツ概要

このコンテンツはWebGLの3D表現を活かした3Dレースゲームです。また、WebSocketを使用しサーバを介して、複数のクライアントでの同時走行が可能なオンラインゲームになっています。同時に、ソケット通信時に発行されるソケットIDをPCとスマートフォンで共有することで、スマートフォンからPC上の車を操作することも可能です。

20141020_img2

クライアントサイドの使用技術

クライアントサイドの構築において、目的・用途に応じて使用した言語やライブラリに関して解説します。

TypeScriptによるクラス設計

クライアントサイドのメインとなるロジックをTypeScriptを使用して設計しました。TypeScriptは大規模JavaScriptアプリケーションに向けてマイクロソフトによって開発されたフリーでオープンソースのプログラミング言語です。

ActionScript3と同じように、1つのTSファイル(TypeScriptファイル)にクラスを1つだけ記述して、ファイル名とクラス名を一致させました。また、モジュール毎にディレクトリを作成して、クラスを格納しています。コードの書き出しは、クラス毎に作成したTSファイルを、クラス毎のJavaScriptファイルに出力(コンパイル)し、Gruntで結合、圧縮して、実際に読み込むJavaScriptファイルにしています。

20141020_img3

Box2DJSを使った2D物理演算

車を走らせたり、障害物と衝突したりといった、ゲームの中核となるロジックはBox2DJSを使用しています。Box2DJSは、質量・速度・摩擦をシミュレーションするJavaScriptの2D物理演算エンジンです。

初期段階のモックアップのイメージですが、まずはこのようにBox2Dを使って、2Dレースゲームを構築しました。この2Dレースゲームの情報を3D表示部分や情報部分(スピードメーター等)やコースデータ管理ロジック、リアルタイム通信ロジックに渡します。

20141020_img4

three.jsの3D表現

WebGLを使った3D表示部分にはthree.jsを使用しています。three.jsは、WebGLを扱うライブラリとしては、最もよく使われているJavaScriptライブラリです。

Blenderというオープンソースの3次元コンピュータグラフィックスソフトウェアを使って、3Dモデルの作成を作成し、three.jsで読み込んで表示しています。

20141020_img5

サーバサイドの使用技術

サーバサイドの技術としてNode.jsを使用しています。Node.jsはサーバーサイドで動作するJavaScriptで、ノンブロッキングI/Oというモデルを採用しています。非同期処理でデータベースへのアクセスとWebページの表示を別々に行ってくれるので、ストレスなく大量のページの表示が出来ます。

ExpressによるWebアプリケーションフレームワークの利用

Node.jsで作成したWebアプリケーションの場合、リクエストURIの解析からファイルの配信など、HTTPサーバの機能を実装しなくてはいけません。これらの基本機能が備わったWebアプリケーションフレームワークを利用することで、非常に手軽にWebアプリケーションを作成できます。今回は、多数開発されているWebフレームワークのなかでも、有名で多く利用されているExpressを利用しました。

ExpressはHTMLのテンプレートエンジンとしてJadeか、ejsを選択することができます。Jadeはインデントが必須です。閉じタグを省略できる代わりに、DOMの入れ子構造に沿って適切にインデントを使用する必要があります。今回は閉じたタグなしで記述できるJadeを選択しています。

Socket.ioによるリアルタイム通信

車の同時走行と、スマートフォンからの車の操作を実現するためには、ブラウザとサーバ双方から、任意のタイミングでデータを送受信する必要があります。このリアルタイム通信を実現するために、Socket.ioを利用しています。Socket.ioはWebSocketなどのリアルタイム通信技術をラップして、シンプルなAPIを提供しているため、通信部分の煩雑さを意識することなく、リアルタイム通信を簡単に構築することができます。スマートフォンからの車の操作を実現するために、接続時に発行されたソケットIDを共有することで、スマートフォンとPCをペアリングして相互通信しています。

MongoDBでラップタイムの保存と走行データの保存

ラップタイムを保存したり、走行データを保存するのにデータベースとしてMongoDBを利用しています。MongoDBは、オープンソースのドキュメント指向データベースです。RDBMSのようにレコードをテーブルに格納するのではなく、ドキュメントと呼ばれる構造的データをオブジェクト形式でデータを管理します。ちなみにNode.jsからMongooseを利用し、MongoDBに接続しています。

まとめ

以上が今回作成したJS-Racingの主な技術解説になります。Webアプリケーションを構築するには、今回解説したように多くの技術が必要となります。このコンテンツで使用した主な技術の全体図をまとめました。

20141020_img6

ぜひ皆さんも、HTML5とJavaScript(クライアントサイド、サーバサイド含む)を使って、Webアプリケーションを作ってみてください。