December 2015

Volume 30 Number 13

ゲーム開発 - Babylon.js: 基本的な Web ゲームのビルド

Raanan Weber

Babylon.js は、ゲームの開発と使いやすさを重視した WebGL ベースの 3D エンジンです。3D エンジンなので、空間におけるメッシュの作成、表示、質感の表現や、光源やカメラの追加などを行うツールが含まれています。Babylon.js はゲームを重視しているため、標準の 3D エンジンには必要のない追加機能もいくつかあります。たとえば、衝突検出、シーン重力、ゲーム指向のカメラ (移動する物体を背後から追跡するカメラなど)、Oculus Rift のような仮想現実 (VR) デバイスなどを、ネイティブにサポートします。また、物理特性エンジン プラグイン システム、ネイティブ オーディオ サポート、ユーザー入力ベースのアクション マネージャーなどもあります。今回のチュートリアルでは、こうした機能をすべて調べます。

このチュートリアルについて

今回のチュートリアルでは、簡単なボウリング ゲームを開発します。まず、ボウリングのレーンを作成し、10 本のピンとボウリングのボールを 1 つ追加して、ボールを投げる機能を用意します。今回のゲームはリリースする域に達していないのは間違いありませんが、Babylon.js のツールを使用してゲームを開発する方法は明らかにします。開発では、意図的に外部ツールを使用しないようにしました。オブジェクト、カメラ、テクスチャなどを、JavaScript コードのみで作成します。

今回のチュートリアルで使用する Babylon.js のバージョンは、安定した最新リリースのバージョン 2.1 です。David Catuhe と Babylon 開発チームは、旧バージョンのフレームワークとの互換性を可能な限り保つよう試みているため、今回のチュートリアルは、将来も、少なくとも Babylon.js の次期メジャー リリースでも正しく動作することだけは想定できます。今回は Visual Studio 2015 Community Edition を使用していますが、お好きな IDE を自由に使用できます。

チュートリアルは 2 部構成になっています。第 1 部の今回は、Babylon.js の基本ビルディング ブロックを大まかに示します。ここでは、メッシュを作成し、その質感を表現して、カメラと光源を追加してから、簡単なユーザー操作を可能にします。第 2 部では、Babylon.js が本領を発揮する部分を取り上げ、衝突と物理法則、オーディオ、ユーザーの操作、特殊な種類のカメラを追加します。

入門編: 新しい Babylon.js プロジェクト

簡単な Babylon.js プロジェクトは、静的 Web サイトです。今回は Visual Studio を使用するため、Visual Studio 組み込みのローカル IIS サーバーを使用して、その静的ファイルをホストします。Visual Studio には静的 Web サイト用のテンプレートがないので、いつもとは違うアプローチが必要です。

最初に、新しい空のソリューションを作成します。Visual Studio を起動して、[ファイル] メニューの [新規作成] をポイントし、[プロジェクト] をクリックします。左側のペインで [その他のプロジェクトの種類]、[Visual Studio ソリューション] の順に選択して、[空のソリューション] をクリックします (図 1 参照)。ソリューション名 (今回は「BabylonBowling」) を入力し、[OK] をクリックします。

Visual Studio での新しい空のソリューションの作成
図 1 Visual Studio での新しい空のソリューションの作成

新しい静的 Web サイトを作成するには、最初に、そのサイトをホストするディレクトリを新規作成する必要があります。空のソリューションを右クリックして、[エクスプローラーでフォルダーを開く] をクリックします (図 2 参照)。

エクスプローラーでソリューションのフォルダーを開く
図 2 エクスプローラーでソリューションのフォルダーを開く

BabylonBowling プロジェクト用に新しいディレクトリを作成し、エクスプローラーを閉じます。

ソリューションを右クリックし、[追加] をポイントして、[既存の Web サイト] をクリックします。新しく作成したフォルダー (ソリューションのフォルダーではなく、先ほど作成したフォルダー) を選択して、[開く] をクリックします。これで、このソリューションの唯一のプロジェクトとして、空の Web サイトが用意されます。

プロジェクトを作成したら、フレームワークとフレームワークの依存関係を追加します。その方法はいくつかあります。最も簡単なのは、NuGet パッケージ マネージャーを使用する方法です。

プロジェクトを右クリックし、[NuGet パッケージの管理] をクリックします。検索フィールド (キーボード ショートカットは Ctrl + E) をクリックし、「babylon」と入力します。その結果として、図 3 のようなウィンドウが表示されます。[BabylonJS] を選択します。バージョン 2.1 (最新の安定バージョン) を選択していることを確認し、[インストール] をクリックします。プレビュー ウィンドウがポップアップしたら [OK] をクリックします。Babylon.js が、デモ シーンを含めて、空のプロジェクトにインストールされます。

NuGet パッケージ マネージャーを使用した Babylon.js の追加
図 3 NuGet パッケージ マネージャーを使用した Babylon.js の追加

npm をパッケージ マネージャーとして使用する場合は、以下のコマンドを使って Babylon.js をインストールします。

npm install babylonjs

パッケージをインストールすると、scripts フォルダーに以下のファイルが用意されます。

  • babylon.js: 縮小バージョンの Babylon.js
  • babylon.max.js: デバッグ バージョンの Babylon.js
  • Oimo.js: チュートリアル第 2 部で使用する Oimo JS 物理特性エンジン
  • poly2tri.js: オプションの三角測量ライブラリ (github.com/r3mi/poly2tri.js、英語)
  • hand-minified.js: ポインター イベントのポリフィル (npm を使用するとこのファイルが用意されないため、以下のコマンドでインストールします)
npm install handjs

NuGet インストーラーは、index.html ファイルと index.js ファイルも作成します。

NuGet パッケージにはエラーがあり、web.config に不要な行が追加されます。このエラーが解決されるまでは、web.config ファイルをダブルクリックして、図 4 で強調している行を削除します (今回のソリューションでは 9 行目)。

強調表示した行を web.config から削除
図 4 強調表示した行を web.config から削除

これで、プロジェクトをテストできるようになります。Ctrl + Shift + W キーを押すか、画面上部のナビゲーション バーにある実行ボタンをクリックして、既定のブラウザーでプロジェクトを開きます。図 5 のように 3D の宇宙船が表示されたら、プロジェクトの準備は完了です。

Babylon 既定の宇宙船
図 5 Babylon 既定の宇宙船

別の IDE を使用している場合は、Babylon.js のドキュメント ページのチュートリアル「Creating Basic Scene」(基本シーンの作成) に従って、準備が完了した現状まで進めてください。NuGet を使用しない場合は、npm を使用して依存関係をインストールすることをお勧めします。チュートリアルについては、bbit.ly/1MXT6WP (英語) を参照してください。

ゼロから始めるには、index.js 内の関数 createScene を削除します。

ビルディング ブロック

まず、エンジンとシーンという 2 つの要素について説明します。

エンジンとは、低レベル WebGL API との通信を担当するオブジェクトです (WebGL 1 はOpenGL ES2 をベースにしており、非常に似た構文を持ちます)。このエンジンが理解しやすい高レベルの API を提供するため、低レベルの WebGL コードを記述する必要がなくなります。また、開発者はエンジンを意識する必要もありません。プロジェクトの初期セットアップを除いて、エンジンを直接使用することはまったくありません。エンジンを使用すれば、特定の低レベル機能を実現できますが、今回は取り上げません。

エンジンを初期化するには、2 つのパラメーターが必要です。1 つは、描画するキャンバスです。キャンバスは 1 つの HTML 要素で、indes.html ファイルに既に含まれています。もう 1 つは、アンチエイリアスの状態 (オン/オフ) です。

現在は空の index.js を開き、以下のコード行を追加します。

function init() {
  var engine = initEngine();
}
function initEngine() {
  // Get the canvas element from index.html
  var canvas = document.getElementById("renderCanvas");
  // Initialize the BABYLON 3D engine
  var engine = new BABYLON.Engine(canvas, true);
  return engine;
}

開発中は、各手順で新しい機能を追加するためにこの init 関数を使用します。作成する要素には、それぞれ独自の init 関数を用意します。

シーンの意味を理解するため、さまざまなページで構成される Web サイトを考えます。1 つの Web ページには、テキスト、画像、イベント リスナーなど、その 1 ページを表示するのに必要なリソースがすべて含まれています。別のページを読み込むと、異なるリソースが読み込まれます。

この 1 つの Web ページとまったく同様に、シーンは 1 つの 3D「ページ」を表示するのに必要なリソースをすべて保持します。このシーンは、メッシュ、カメラ、光、ユーザーの操作など、すべてのリソースを含むため、非常に大きくなる可能性があります。しかし、あるページから別のページに移動するためには、新しいシーンが必要になります。シーンには、独自のリソースをレンダリングする役割のほかに、必要な情報をエンジンとやり取りする役割もあります。今回のボウリング ゲームに必要なシーンは 1 つだけです。ただし、新しいステージやボーナス ステージの追加を予定している場合は、新しいシーンを使用することになります。

シーンを初期化するのに必要なのは、先ほど作成したエンジンだけです。以下のコード行を index.js に追加します。

function createScene(engine) {
  var scene = new BABYLON.Scene(engine);
  // Register a render loop to repeatedly render the scene
  engine.runRenderLoop(function () {
      scene.render();
  });
}

まず、シーン オブジェクトを作成します。それ以降の数行は、エンジンと対話しているだけです。レンダリング ループを実行しながら、毎回、特定のシーンをレンダリングするようエンジンに指示しています。

実際にシーンを追加するには、以下のコード行を init 関数の末尾に追加します。

var scene = createScene(engine);

先に進む前にやっておくべきことがまだ 2 つあります。ブラウザ ウィンドウのサイズを変更すると、キャンバスのサイズも変更されます。エンジンは、内部の幅と高さのサイズも変更して、シーンの全体像を正しく保つ必要があります。そこで、initEngine 関数の「return engine;」行の直前に、以下のコード行を追加します。このステートメントが、シーンの全体像を正しく保ちます。

// Watch for browser/canvas resize events
window.addEventListener("resize", function () {
  engine.resize();
});

もう 1 つ、新しい init 関数を使用するように、index.html を変更します。index.html を開いて、createScene への呼び出しを含む script タグを見つけます。createScene を init に変更して index.html を保存した後、それを閉じます。

シーンには、シーンのレンダリングをデバッグできる、非常に高度なデバッグ レイヤーがあります。このレイヤーは、レンダリングされるメッシュの数や、現在の 1 秒あたりのフレーム数 (FPS) を示します。デバッグでは、テクスチャリングや影などの機能をオフにすることができるため、足りないメッシュを簡単に特定できます。デバッグ レイヤーは、以下のように簡単にオンにできます。

scene.debugLayer.show();

こうすることで、シーンを独自にデバッグできるようになります。

これでエンジンとシーンを用意できたので、カメラ、光源、メッシュを追加して、ボウリング場のシーンの作成に着手できます。

カメラ

Babylon.js はさまざまな種類のカメラを用意しており、それぞれ固有の目的があります。ゲームのカメラを選ぶ前に、最も一般的な種類のカメラを確認しておきます。

  • Free Camera は、一人称の視点で対象物を捕らえるカメラです。キーボードの矢印キーを使用してシーンの中を自由に動かし、マウスを使用して方向を定めることができます。オプションで重力や衝突検出も有効にできます。
  • Arc Rotate Camera は、特定の対象物の周囲を回転するカメラです。マウス、キーボード、またはタッチ イベントを使用して、ユーザーはあらゆる方向からオブジェクトを見ることができます。
  • Touch Camera は、入力にタッチ イベントを使用する 1 人称カメラです。モバイル プラットフォームに適しています。
  • Follow Camera は、特定の対象物を背後から自動的に追跡するカメラです。

Babylon.js は WebVR やデバイス指向のカメラをネイティブにサポートします。つまり、Oculus Rift や Google Cardboard などのデバイスへの対応が非常に簡単です。

バージョン 2.1 で導入された新しい考え方により、各種類のカメラが 3D 対応になります。したがって、さまざまな種類のカメラを、Oculus Rift 式の立体視や赤青眼鏡 (3D アナグリフ) に対応するように設定できます。図 6 は、アナグリフに対応しないカメラを使ってレンダリングした宇宙船のシーンを示し、図 7 は、立体カメラを使用したシーンを示します。

3D アナグリフ カメラ
図 6 3D アナグリフ カメラ

立体カメラ
図 7 立体カメラ

今回のボウリング ゲームには、2 種類のカメラを使用します。1 つは、プレイヤーのメイン カメラで、ボウリングのボールを投げる位置に設置します。これにうってつけなのは Free Camera です。もう 1 つ、ボウリングのボールが転がってからピンに当たるまで、後ろからそのボールを追跡するカメラも追加します。

最初に、Free Camera を追加します。createFreeCamera 関数は、1 つの引数としてシーンを表す変数を受け取ります。

function createFreeCamera(scene) {
  var camera = new BABYLON.FreeCamera(
    "player camera", BABYLON.Vector3.Zero(), scene);
  return camera;
}

このカメラはシーンの座標 (0,0,0) に作成します。後ほど、(必要になったときに) この関数を拡張して、カメラをさらに構成します。

当然ですが、この関数を init 関数の末尾に忘れずに追加します。

...
// Create the main player camera
var camera = createFreeCamera(scene);
// Attach the control from the canvas' user input
camera.attachControl(engine.getRenderingCanvas());
// Set the camera to be the main active camera
scene.activeCamera = camera;

attachControl 関数は、特定のカメラに必要なネイティブ JavaScript イベント (マウス、タッチ、キーボード入力の各イベントなど) のリスナーを登録します。シーンのアクティブ カメラを設定することで、このカメラをレンダリングに使用することをシーンに指示します。

もう 1 つのカメラは、第 2 部でボールを投げれるようにしてから追加します。

レーンの作成

ボウリングのレーンは、比較的シンプルな幾何学構造です。まず、ボウリング レーンの実サイズを示すいくつかの定数をメートル単位で設定します。メートルを使用する理由は、物理特性エンジンのためです (詳しくは第 2 部で説明します)。

この定数は、プロジェクト ファイルで確認できます。これらの値を算出するために、オンラインから利用できる、ボウリングのレーンに関する情報を使用します。

定数を設定したら、ボウリングのレーンを構築するメッシュを作成できるようになります。図 8 に (2D での) プランを示します。最初に、メッシュを作成します。メッシュにマテリアルを加えるテクスチャリングは、その後に行います。

ボウリング レーンのシーンの 2D プラン
図 8 ボウリング レーンのシーンの 2D プラン

まず、シーンにグローバルな床面を作成します。

function createFloor(scene) {
  var floor = BABYLON.Mesh.CreateGround("floor", 100, 100, 1, scene, false);
  return floor;
}

上記のコードは、シンプルな 100 メートル四方の床面を作成します。Babylon.js の内部関数を使用して作成したメッシュは、すべてシーンの座標 (0,0,0) に中央揃えで作成されます。メッシュを変換し、シーン内の適切な位置に配置する重要な変数が 3 つあります。

  • mesh.position: 空間内でのメッシュの位置を表すベクトル
  • mesh.scaling: 各軸のメッシュの倍率
  • mesh.rotation: 各軸での回転のラジアン単位のオイラー角 (四元数の方が使いやすい場合は mesh.rotationQuaternion を使用可)

init 関数にこの関数を追加してシーンを開始すると、興味深いことに、追加したはずの床面がまったく表示されません。その理由は、カメラと床面の両方を、空間の同じ座標 (0,0,0) に作成したためです。地面は完全に平坦なので、上 (または下) から見なければ画面上に表示されることはありません。createCamera 関数内のカメラ初期化に戻り、カメラの初期位置を表す 2 つ目の変数を新しいベクトルに変更します。これにより、カメラは地面から 1.7 単位 (今回の場合は 1.7 m) 上に移動します。

var camera = new BABYLON.FreeCamera(
  "cam", new BABYLON.Vector3(0,1.7,0), scene);

ここでシーンを起動すると、画面の半分より少し上まで広がる床面が表示されます (図 9 参照)

シーンへの床面の追加
図 9 シーンへの床面の追加

試しに矢印キーやマウスを使用してカメラを動かして、Free Camera の使い方を理解します。

さて、床面が真っ黒に表示されています。そう、光を忘れています。ここで、新しく createLight 関数を追加します。これについては、後ほど説明します。

function createLight(scene) {
  var light = new BABYLON.DirectionalLight(
    "dir01", new BABYLON.Vector3(-0.5, -1, -0.5), scene);
  // Set a position in order to enable shadows later
  light.position = new BABYLON.Vector3(20, 40, 20);
  return light;
}

忘れずに以下のコードを init 関数に追加します。

var light = createLight(scene);

Babylon.js には、4 種類の光があります。

  • 半球型: 地面の色 (暗くなっていくピクセル)、空の色 (明るくなっていくピクセル)、および鏡面反射色があらかじめ定義されている環境光。
  • 点型: 太陽のように、1 つの点からすべての方向に向かって拡散する光。
  • スポット型: 名前が示すとおり、1 つの点から特定の方向に、特定の放射半径で放たれる光。この光により、投影が可能です。
  • 指向型: あらゆる場所方特定の方向に放出される光。太陽は点型の光ですが、指向型の光の方が、太陽光を適切にシミュレーションできます。この光も投影が可能で、今回の例で使用しています。

これで、床面が白になります。Babylon.js は、マテリアルが何も割り当てられていないメッシュには、それぞれ既定で白のマテリアルを割り当てます。

レーン自体は箱型にして、作成した床面の上に配置します。

function createLane(scene) {
  var lane = BABYLON.Mesh.CreateBox("lane", 1, scene, false);
  lane.scaling = new BABYLON.Vector3(
    laneWidth, laneHeight, totalLaneLength);
  lane.position.y = laneHeight / 2; // New position due to mesh centering
  lane.position.z = totalLaneLength / 2;
  return lane;
}

何度も繰り返しますが、この関数を呼び出すコードを init 関数に追加するのを忘れないでください。

上記のコードで、スケーリング パラメーターの使い方を確認できます。1x1x1 のサイズの立方体を作成し、あらかじめ定義した定数に合わせてスケーリングを変更しています。

同じ手法を使って、レーンの両側にガーターにする 2 つの箱型を作成します (誤った方向にボールを投げると、このガーターにボールが落ちます)。試しにガーターを作成してみてください。その方法は、本稿付属のプロジェクトで確認できます。

ボウリングのピンとボール

今のところ不足しているのは、ボウリングのピンとボールです。ピンを作成するには、円柱を使用します。1 本の円柱を何本 (正確には 10 本) も複製します。Babylon.js では、このような複製物をインスタンスと呼びます。インスタンスは、空間内での変換を除けば、メッシュの正確なコピーです。つまり、インスタンスのジオメトリとテクスチャを変更することはできませんが、位置、倍率、回転を変更できます。今回は、最初に作成したオブジェクトをシーン内では使用しないことにしました。10 本のピンが必要なので、最初に 1 本のピンを作成し、そのピンを無効にしてから、あらかじめ定義した 10 箇所に、そのピンのインスタンスを 10 本作成します。

function createPins(scene) {
  // Create the main pin
  var mainPin = BABYLON.Mesh.CreateCylinder(
    "pin", pinHeight, pinDiameter / 2, pinDiameter, 6, 1, scene);
  // Disable it so it won't show
  mainPin.setEnabled(false);
  return pinPositions.map(function (positionInSpace, idx) {
    var pin = new BABYLON.InstancedMesh("pin-" + idx, mainPin);
    pin.position = positionInSpace;
    return pin;
  });
}

この関数で使用していて定義が見つからない変数は、プロジェクト ファイル内で定義しています。たとえば、10 本のピンすべてのグローバルな位置をもつ配列 pinPositions などです。

さて、ボウリングのボールです。ボウリングのボールはシンプルな球体で、指を入れる穴が 3 つあります。球体を作成するには、以下のように Babylon.js が提供する CreateSphere 関数を使用します。

var sphere = BABYLON.Mesh.CreateSphere("sphere", 12, 0.22, scene);

ここで、3 つの穴を開ける必要があります。そのためには、Babylon.js に統合されている空間領域構成法 (CSG) を使用します。CSG により、既存のメッシュに別のメッシュを付け足したり、既存のメッシュから別のメッシュを取り除くことができます。さらには、幾何図形も相互に付け加えたり、取り除いたりできます。つまり、2 つのメッシュが交差する場合、片方のメッシュを「取り除いて」、メッシュを変更することができます。今回は、球体に丸い穴を 3 つ開ける必要があります。これにも円柱を使用します。

まず、最初の穴に使用する円柱を作成します。

var cylinder = BABYLON.Mesh.CreateCylinder(
  "cylinder", 0.15, 0.02, 0.02, 8, 1, scene, false);

次に、円柱と球体が交差するように、円柱の位置を変えます。

cylinder.position.y += 0.15;

続いて、CSG オブジェクトを作成し、球体から円柱をくり抜きます。

var sphereCSG = BABYLON.CSG.FromMesh(sphere);
var cylinderCSG = BABYLON.CSG.FromMesh(cylinder);
sphereCSG.subtractInPlace(cylinderCSG);
var ball = sphereCSG.toMesh("test", sphere.material, scene, false);

図 10 では、球体と円柱の外観、隣に CSG を使用して作成したボウリングのボールを示します。

ボウリング ボールの作成
図 10 ボウリング ボールの作成

図 11babylonjs-playground.com/#BIG0J の Playground に、ボールをゼロから作成するために使用したコードをすべて示します。

図 11 CSG を使用したボウリング ボールの作成

// The original sphere, from which the ball will be made
var sphere = BABYLON.Mesh.CreateSphere("sphere", 10.0, 10.0, scene);
sphere.material = new BABYLON.StandardMaterial("sphereMat", scene);
// Create pivot-parent-boxes to rotate the cylinders correctly
var box1 = BABYLON.Mesh.CreateBox("parentBox", 1, scene);
var box2 = box1.clone("parentBox");
var box3 = box1.clone("parentBox");
// Set rotation to each parent box
box2.rotate(BABYLON.Axis.X, 0.3);
box3.rotate(BABYLON.Axis.Z, 0.3);
box1.rotate(new BABYLON.Vector3(0.5, 0, 0.5), -0.2);
[box1, box2, box3].forEach(function (boxMesh) {
// Compute the world matrix so the CSG will get the rotation correctly
  boxMesh.computeWorldMatrix(true);
  // Make the boxes invisible
  boxMesh.isVisible = false;
});
// Create the 3 cylinders
var cylinder1 = BABYLON.Mesh.CreateCylinder(
  "cylinder", 4, 1, 1, 30, 1, scene, false);
cylinder1.position.y += 4;
cylinder1.parent = box1;
var cylinder2 = cylinder1.clone("cylinder", box2);
var cylinder3 = cylinder1.clone("cylinder", box3);
// Create the sphere's CSG object
var sphereCSG = BABYLON.CSG.FromMesh(sphere);
// Subtract all cylinders from the sphere's CSG object
[cylinder1, cylinder2, cylinder3].forEach(function (cylinderMesh) {
  sphereCSG.subtractInPlace(BABYLON.CSG.FromMesh(cylinderMesh));
});
// Create a new mesh from the sphere CSG
var ball = sphereCSG.toMesh("bowling ball", sphere.material, scene, false);

テクスチャ

作成したすべてのメッシュには、既定で白のマテリアルが用意されます。シーンを魅力的にするには、他のマテリアルを追加します。Babylon.js の標準マテリアル (既定のシェーダー) には、操作可能な定義がたくさんありますが、ここでは取り上げません (Babylon.js 既定のシェーダーの詳細については、materialeditor.raananweber.com (英語) の BabylonJS Material Editor を参照してください)。ただし、レーンとボウリングのボールにテクスチャを設定する方法は説明しておきましょう。

ボウリングのボールにテクスチャを設定するため、ここでは手続き型テクスチャという Babylon.js のもう 1 つのすばらしい機能を使用します。手続き型テクスチャは、2D 画像を使用する標準のテクスチャではありません。これは、プログラムで作成し、GPU (CPU ではありません) によって生成されるテクスチャで、シーンのパフォーマンスを大幅に向上します。Babylon.js には、樹木、レンガ、火、雲、草など、多種多様な手続き型テクスチャがあります。ここでは、大理石模様のテクスチャを使用します。

ボールのメッシュを作成する行の跡に次のコードを追加して、大理石模様の緑色のボールにします (図 12 参照)。

var marbleMaterial = new BABYLON.StandardMaterial("ball", scene);
var marbleTexture = new BABYLON.MarbleProceduralTexture(
  "marble", 512, scene);
marbleTexture.numberOfTilesHeight = 2;
marbleTexture.numberOfTilesWidth = 2;
marbleMaterial.ambientTexture = marbleTexture;
// Set the diffuse color to the wanted ball's color (green)
marbleMaterial.diffuseColor = BABYLON.Color3.Green();
ball.material = marbleMaterial;

大理石模様のテクスチャを適用したボール
図 12 大理石模様のテクスチャを適用したボール

レーンに樹木柄のテクスチャを追加するには、標準マテリアルの拡散テクスチャを使用します。しかし、レーンのマテリアルについて説明しておきたいのは、この点ではありません。実際のボウリング レーンを見ると、その上には複数のドットの集まりや、横に並んだ矢印 (三角形) があるのがわかります。この図柄のシミュレーションを行うために、レーン上のドットと矢印をすべて収容する非常に大きなテクスチャを使用してもかまいませんが、巨大なテクスチャはパフォーマンスに悪影響を及ぼし、画質を下げる可能性があります。

今回は、Babylon.js 2.1 で導入された新機能のデカールも使用します。デカールとは、既にテクスチャを設定したメッシュの上に「描画」する手段です。たとえば、壁の弾痕を擬似的に付けたり、今回のように、ボウリングのレーンに装飾を施したりします。デカールもメッシュの集まりです。そのため、標準マテリアルを使用してテクスチャを設定することができます。図 13 では 4 本の線を追加する方法を示し、図 14 はデカールを加えた後のレーンと、手続き型テクスチャ (レンガと草) をマテリアルとして使用した床面とガーターの外観を示しています。

図 13 4 本線のデカールの追加

// Set the decal's position
var foulLinePosition = new BABYLON.Vector3(0, laneHeight, foulLaneDistance);
var decalSize = new BABYLON.Vector3(1,1,1);
// Create the decal (name, the mesh to add it to, position, up vector and the size)
var foulLine = BABYLON.Mesh.CreateDecal("foulLine", lane, foulLinePosition, BABYLON.Vector3.Up(), decalSize);
// Set the rendering group so it will render after the lane
foulLine.renderingGroupId = 1;
// Set the material
var foulMaterial = new BABYLON.StandardMaterial("foulMat", scene);
foulMaterial.diffuseTexture =
  new BABYLON.Texture("Assets/dots2-w-line.png", scene);
foulMaterial.diffuseTexture.hasAlpha = true;
foulLine.material = foulMaterial;
// If the action manager wasn't initialized, create a new one
scene.actionManager = new BABYLON.ActionManager(scene);
// Register an action to generate a new color each time I press "c"
scene.actionManager.registerAction(new BABYLON.ExecuteCodeAction({
  trigger: BABYLON.ActionManager.OnKeyUpTrigger, parameter: "c" },
  // The function to execute every time "c" is pressed"
  function () {
    ball.material.diffuseColor =
      new BABYLON.Color3(Math.random(), Math.random(), Math.random());
  }
));

デカール追加後のレーン
図 14 デカール追加後のレーン

ユーザー入力 - Babylon.js アクション マネージャー

機能満載のゲーム エンジンの名に恥じず、Babylon.js にはユーザー入力を簡単に操作する方法があります。ここでは、C キーを使用して、ボールの色を変更できるようにします。C キーが押されるたびに、ボールの色をランダムで変えるようにします。

// If the action manager wasn't initialized, create a new one
scene.actionManager = new BABYLON.ActionManager(scene);
// Register an action to generate a new color each time I press C
scene.actionManager.registerAction(
  new BABYLON.ExecuteCodeAction({ trigger:
  BABYLON.ActionManager.OnKeyUpTrigger, parameter: "c" },
  // The function to execute every time C is pressed
  function () {
    ball.material.diffuseColor =
      new BABYLON.Color3(Math.random(), Math.random(), Math.random());
  }
));

Babylon.js のアクション マネージャーは、トリガーに応じて動作を制御する強力なツールです。トリガーには、マウスの移動やクリック、メッシュの交差、キーボード入力を設定できます。選択できるトリガーとアクションはたくさんあります。それらをすべて確認するには、Babylon.js のチュートリアル サイト (bit.ly/1MEkNRo、英語) を参照してください。

今回はこのアクション マネージャーを使用して、ボールの操作とシーンのリセットを行います。アクションの追加については、このチュートリアルの第 2 部で取り上げます。

外部リソースの使用

ここでは、Babylon.js の内部関数を使用して、必要なメッシュを作成しました。しかし、ほとんどの場合、これだけでは不十分です。Babylon.js は球体や立方体から複雑なリボンまで、多くのメッシュを提供しますが、人間、Web でプレイできる Doom のための武器、スペース インベーダーのクローン用宇宙船など、複雑なモデルを作成するのは困難です。

Babylon.js は、Blender や 3D-Studio などの多くの著名な 3D ツール向けのエクスポート プラグインを提供しています。また、すばらしい Clara.io からモデルをエクスポートして、.babylon ファイルをダウンロードすることもできます。

Babylon.js は、メッシュ、カメラ、光、アニメーション、ジオメトリなどの情報を含むシーン全体を保持する独自形式のファイルを使用します。そのため、必要であれば、シーン全体をモデル化するためだけに Blender を使用してもかまいません。1 つのメッシュをインポートすることも可能です。

ただし、このテーマは、今回のチュートリアルでは取り上げません。ここで、Babylon.js だけを使用してシンプルなゲームを開発する方法のみを取り上げます。

次回の予定

今回は、Babylon.js に統合されている機能の多くを取り上げることができませんでした。Babylon.js には非常に多くの機能があるので、限りない可能性を確かめるために、Playground (babylonjs-playground.com、英語)、ドキュメンテーション ページ (doc.babylonjs.com、英語)、Babylon.js のメイン ページ (babylonjs.com、英語) を参照することを強くお勧めします。このチュートリアルで難しく感じる部分があれば、連絡をください。あるいは、非常に活気あふれる HTML5 Game Devs フォーラム (bit.ly/1GmUyzq、英語) で、Babylon.js を熟知している開発者に問い合わせてみてください。

次回は、実際のゲームプレイを作成する予定です。物理運動の法則や衝突検知、ボールを投げる機能やサウンドなどの効果を追加します。


Raanan Weber は、IT コンサルタントであり、フルスタック開発者であり、夫であり、父親でもあります。余暇には、Babylon.js などのオープン ソース プロジェクトに貢献しています。彼のブログは blog.raananweber.com (英語) で公開されています。

この記事のレビューに協力してくれたマイクロソフト技術スタッフの David Catuhe に心より感謝いたします。