# 游戲開發 - Babylon.js: 構建 Web 基本游戲
作者?[Raanan Weber](https://msdn.microsoft.com/zh-cn/magazine/mt149362?author=Raanan+Weber)?| 2015 年 12 月 |?[獲取代碼](http://download.microsoft.com/download/D/5/4/D54647CC-A404-4374-B7EF-E469FB5136B9/Code_Weber.Babylon.1215.zip)
Babylon.js 是一款基于 WebGL 的 3D 引擎,主要以游戲開發和易用性為主。作為 3D 引擎,它包含的工具可用于創建和顯示網格,以及在空間中設置紋理,并能添加光源和照相機。由于是以游戲為主,因此 Babylon.js 還具有常規 3D 引擎不需要的一些額外功能。它提供了對碰撞檢測、場景重力、面向游戲的照相機(例如,跟蹤移動對象的跟隨照相機),以及對 Oculus Rift 和其他虛擬現實 (VR) 設備的本地支持。它具有物理引擎插件系統、本地音頻支持、基于用戶輸入的操作管理器等。在本教程中,我將介紹所有這些功能。
## 關于本教程
在本教程中,我將開發一個簡單的保齡球游戲。我將創建一個保齡球球道,添加 10 個保齡球瓶和一個保齡球,并提供擲球功能。我的游戲當然不會發布,但我會用它來向您展示如何使用 Babylon.js 提供的工具開發游戲。在開發期間,我會刻意避免使用任何外部工具。我將只使用 JavaScript 代碼創建對象、照相機、紋理等。
在本教程中,我將使用最新的穩定版本 Babylon.js 2.1。David Catuhe 和 Babylon 開發團隊正在嘗試盡可能保持框架的后向兼容性,因此,我只能假設本教程適用于今后發布的版本(至少在下一主要版本發布之前)。我使用的是 Visual Studio 2015 Community Edition,但您也可以根據需要使用任意 IDE。
本教程分為兩個部分。在本文中,我將概述 Babylon.js 的構建基塊。我將創建網格、設置紋理、添加照相機和光源,并啟用簡單的用戶交互。在第二部分中,我將添加碰撞和物理特性、音頻、用戶操作和特殊的照相機類型,從而展現 Babylon.js 的真正閃光之處。
## 入門: 新建 Babylon.js 項目
簡單的 Babylon.js 項目是一個靜態網站。由于我使用的是 Visual Studio,因此我將使用嵌入 Visual Studio 的本地 IIS 服務器來托管這些靜態文件。Visual Studio 沒有靜態網站模板,所以需要采用不同的方法。
首先,新建一個空白解決方案。打開 Visual Studio,然后轉到“文件 | 新建 | 項目”。選擇左窗格中的“其他項目類型”,然后選擇“空白解決方案”(如圖 1?所示)。為解決方案命名(我命名的是“BabylonBowling”),然后單擊“確定”。
?
圖 1:在 Visual Studio 中新建空白解決方案
若要新建靜態網站,您首先需要新建一個托管目錄。右鍵單擊空解決方案,然后單擊“在文件資源管理器中打開文件夾”(如圖 2?所示)。

圖 2:在文件資源管理器中打開解決方案文件夾
為 BabylonBowling 項目新建一個目錄,然后關閉文件資源管理器。
右鍵單擊解決方案,然后選擇“添加 | 現有網站”。選擇新創建的文件夾(務必選擇剛創建的文件夾,而不是解決方案的文件夾),然后單擊“打開”。此時,您應該有一個空白網站作為此解決方案的唯一項目了。
創建項目后,您需要添加框架和框架依賴項。有幾種方法可以做到這一點。最簡單的方法是使用 NuGet 包管理器。
右鍵單擊項目,然后選擇“管理 NuGet 包”。單擊搜索字段(鍵盤快捷方式為 Ctrl+E),然后鍵入 babylon。此時,您會看到一個窗口(如圖 3?所示)。選擇“BabylonJS”。請確保選定版本是 2.1(或最新的穩定版本),然后單擊“安裝”。在彈出的“預覽”窗口(若有)中,單擊“確定”,然后 Babylon.js 會安裝至您的空項目中(包括演示場景)。
?
圖 3:使用 NuGet 包管理器添加 Babylon.js
如果您將 npm 用作包管理器,則可以使用下列命令安裝 Babylon.js:
~~~
npm install babylonjs
~~~
在安裝包后,您應該會在腳本文件夾中看到下列文件:
* babylon.js:Babylon.js 的簡化版本
* babylon.max.js:Babylon.js 的調試版本
* Oimo.js:Oimo JS 物理引擎,本教程的第二部分中將會用到
* poly2tri.js:可選的三邊轉換庫 ([github.com/r3mi/poly2tri.js](http://github.com/r3mi/poly2tri.js))
* hand-minified.js:指針事件填充代碼;在使用 npm 時缺失,因此使用下列命令進行安裝:
~~~
npm install handjs
~~~
NuGet 安裝程序也會創建 index.html 文件和 index.js 文件。
NuGet 包中的錯誤會在 web.config 中添加不需要的行。請雙擊此文件,并刪除圖 4?中突出顯示的行(在我的解決方案中,為第 9 行),直至修復完成。

圖 4:從 web.config 中刪除突出顯示的行
您現在可以測試項目了。使用 Ctrl+Shift+W 或通過單擊頂部導航欄的“運行”按鈕,在您的默認瀏覽器中打開項目。如果您看到圖 5?中顯示的 3D 宇宙飛船,則表明您的項目已準備就緒。

圖 5:Babylon 默認宇宙飛船
如果您使用的是其他 IDE,只需按 Babylon.js 文檔頁中的“創建基本場景”教程執行操作,即可達到當前狀態。如果您沒有使用 NuGet,我仍然建議您使用 npm 安裝依賴項。有關此教程,請訪問[bit.ly/1MXT6WP](http://bit.ly/1MXT6WP)。
若要從頭開始,請刪除 index.js 中的 createScene 函數。
## 構建基塊
我首先將介紹的兩個元素是引擎和場景。
引擎是負責與低級 WebGL API 通信的對象(WebGL 1 以 OpenGL ES2 為基礎,語法非常相似)。引擎提供了更易于理解的較高級 API,這樣您就不必編寫低級 WebGL 代碼了。這對開發者來說也是透明的。除了初始項目設置之外,我根本不會直接使用引擎。雖然使用此引擎可以完成特定的較低級功能,但我不會涉及這一點。
引擎需要兩個參數才能初始化。第一個參數是用于繪制的畫布。畫布是 index.html 中已有的 HTML 元素。第二個參數是抗鋸齒狀態(開或關)。
打開當前的空白 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 函數為每一步添加新功能。我創建的每個元素都會有自己的函數。
為了更好地了解場景代表什么,請將場景看成是包含不同網頁的網站。一個網頁中包含文本、圖像、事件監聽器以及呈現一個網頁所需的其他所有資源。加載不同的網頁就是加載不同的資源。
如同一個網頁,場景包含顯示一個 3D“網頁”所需的資源。 此場景可能非常大,包含大量資源(網格、照相機、光、用戶操作等)。不過,若要從一個網頁移到另一個網頁,我建議使用新場景。場景也負責呈現它自己的資源,并將所需的信息傳達給引擎。保齡球游戲只需要一個場景。不過,如果我計劃添加新等級或獎分游戲,那么我會使用新場景創建它們。
若要初始化場景,只需要我創建的引擎。在 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);
~~~
在繼續前,我還需要執行兩項操作。當您重設瀏覽器窗口大小時,畫布也會重設大小。引擎還必須重設其內部寬度和高度,以使場景比例正確。就在返回引擎前,向 initEngine 函數添加下列代碼行;聲明會使場景比例正確。
~~~
// Watch for browser/canvas resize events
window.addEventListener("resize", function () {
? engine.resize();
});
~~~
第二項操作是,將 index.html 更改為使用新的 init 函數。打開 index.html,然后查找包含 createScene 調用的腳本標記。將 createScene 更改為 init,然后保存 index.html 并關閉。
此場景的調試層極為高級,可方便您調試正在呈現的場景。它顯示正在呈現的網格數以及當前的每秒幀數 (FPS)。借助它,您可以關閉紋理和陰影等功能,并能輕松找到丟失的網格。開啟調試層非常簡單:
~~~
scene.debugLayer.show();
~~~
開啟后,您便能自行調試場景。
此時,我已有引擎和場景,我可以開始添加照相機、光源和網格來創建我的保齡球館場景了。
## 相機
Babylon.js 提供很多類型的照相機,每個都有自己的特定用途。在為游戲選擇照相機之前,讓我們先回顧一下最常見的類型:
* 自由照相機是一種由第一人稱拍攝的照相機。使用鍵盤上的箭頭鍵,可以自由地在整個場景中移動它,并能使用鼠標設置方向。還可以視需要選擇啟用重力和碰撞檢測。
* 弧形旋轉照相機用于圍繞特定的目標旋轉。使用鼠標、鍵盤或觸摸事件,用戶可以全方位地查看對象。
* 觸控照相機是一種使用觸摸事件作為輸入的自由照相機。它適合所有的移動平臺。
* 跟隨照相機自動跟蹤特定目標。
Babylon.js 對 WebVR 和設備方向照相機提供本地支持。也就是說,您很容易就可以將此類設備列為 Oculus Rift 或 Google Cardboard。
第 2.1 版中引入的新概念讓每種類型的照相機都支持 3D。也就是說,每種類型的照相機都可以設置為適應 Oculus Rift 式立體視圖和紅藍眼鏡(3D 立體)。圖 6?展示了使用非立體照相機呈現的宇宙飛船場景,圖 7?展示了使用立體照相機呈現的場景。
?
圖 6:非 3D 立體照相機

圖 7:立體照相機
對于我的保齡球游戲,我將使用兩種類型的照相機。第一種是玩家的主要照相機,用于設置保齡球的擲出位置。這就體現了自由照相機的確切用途。我還想添加不同的視圖,即當球在球道中時,我想跟隨它直到其撞擊到保齡球瓶。
首先,我將添加自由照相機。createFreeCamera 函數將場景視作一個變量:
~~~
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 事件監聽器(如鼠標、觸摸或鍵盤輸入的事件監聽器)。設置場景的活動照相機可以指示場景,此照相機應該用于呈現。
在啟用擲球后,我將在第二部分中添加第二種照相機。
## 創建球道
保齡球球道是一種相對簡單的幾何結構。我將先設置一些常量作為保齡球球道的實際尺寸(以米為單位)。我以米為單位是因為使用的是物理引擎(我將在本文的第二部分中予以解釋)。
您可以在項目文件中看到常量。為了計算這些值,我參考了網上關于保齡球球道的可用信息。
在設置這些常量后,我就可以開始創建構成保齡球球道的網格了。圖 8?展示了我的 (2D) 規劃。我將先創建網格。然后,我會設置網格紋理(即指定材料)。
?
圖 8:保齡球球道場景的 2D 規劃
首先,我將為場景創建全場地板:
~~~
function createFloor(scene) {
? var floor = BABYLON.Mesh.CreateGround("floor", 100, 100, 1, scene, false);
? return floor;
}
~~~
這會創建一塊簡單的 100x100 米地板。使用 Babylon.js 內部函數創建的所有網格都集中位于場景的 0,0,0 位置處。有三個重要的變量用于轉換網格并在場景中正確定位網格:
* mesh.position 是網格在空間中的位置的矢量
* mesh.scaling 是網格在每個軸中的比例系數
* mesh.rotation 是每個軸的旋轉歐拉角(以弧度為單位);如果您更愿意使用四元(我知道我是這樣),則可以改用 mesh.rotationQuaternion
在向 init 函數添加函數并啟動場景后,我注意到一個有趣的現象,即我根本看不到我所添加的地板! 原因是照相機和地板兩者均創建于空間的同一點 (0,0,0)。由于地面是完全平坦的,因此只有從高空(或低空)審視才會在屏幕上看到它。回到 createCamera 函數中的照相機初始化,我將第二個變量(照相機的初始位置)更改為一個新矢量。現在,照相機離地面有 1.7 個單位(在此示例中,單位為米):
~~~
var camera = new BABYLON.FreeCamera(
? "cam", new BABYLON.Vector3(0,1.7,0), scene);
~~~
如果您現在啟動場景,則會看到地板拉伸超過屏幕的一半(如圖 9?所示)。

圖 9:向場景添加地板
嘗試使用箭頭和鼠標進行移動,以掌握如何控制自由照相機。
您會注意到地板是全黑的。就缺少光! 我將添加新的函數 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 提供四種類型的光:
* 半球光: 環境光,用地面顏色(正面向下的像素)、天空顏色(正面向上的像素)和反射顏色預定義。
* 點光: 從一個點向所有方向發射的光(如陽光)。
* 投射光: 從名稱我們就可以看出,這是從一個點以特定發射半徑向特定方向發射的光。此類光可以產生陰影。
* 定向光: 從任意位置向特定方向發射的光。雖然陽光可以為點光,但定向光可以更好地模擬陽光。此類光也可以產生陰影,我的示例中使用的就是這種光。
現在,地板將變成白色。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 的盒子,然后將它的縮放設置更改為適應我預定義的常量。
使用同樣的技術,我創建了兩個盒子,它們將用作我球道兩邊的球槽(若以錯誤的方向擲出,則球會落入此槽)。您可以自己嘗試創建看看,也可以查看隨附的項目,看我是如何創建的。
## 保齡球瓶和球
現在就差保齡球瓶和球了。為了創建保齡球瓶,我將使用圓柱體,只需將一個圓柱體倍增多次即可(確切地說,是 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;
? });
}
~~~
此函數中缺少的變量可以在項目文件中找到,包括 pinPositions(包含所有 10 個保齡球瓶的全局位置的數組)。
現在就差保齡球了。保齡球是一種簡單的球體,上有 3 個方便手指插入的孔。為了創建此球體,我將使用 Babylon.js 提供的 CreateSphere 函數:
~~~
var sphere = BABYLON.Mesh.CreateSphere("sphere", 12, 0.22, scene);
~~~
現在,我需要鉆孔。為此,我將使用已集成到 Babylon.js 中的構造實體幾何 (CSG) 功能。借助此功能,我可以向現有網格添加網格或從中去掉網格,或者可以向另一個幾何體添加幾何體或從中去掉幾何體(如果能這樣,就更好了)。也就是說,如果兩個網格相交,我可以從中“去掉”一個網格,獲得另一個經過更改的網格。在我的示例中,我想在一個球體中創建三個圓孔。圓柱體就完全適合。
首先,我將創建用于第一個孔的圓柱體:
~~~
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:創建保齡球
圖 11?和?[babylonjs-playground.com/#BIG0J](http://babylonjs-playground.com/#BIG0J)?上的園地均展示了從頭開始創建保齡球的全部代碼。
圖 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](http://materialeditor.raananweber.com/)?上的 BabylonJS 材料編輯器。) 不過,我將介紹我是如何設置球道和保齡球的紋理的。
為了設置保齡球的紋理,我將使用另一項精彩的 Babylon.js 功能,即過程化紋理。過程化紋理不是使用 2D 圖像的標準紋理,而是以編程方式創建的紋理(由 GPU(而不是 CPU)生成),能夠對場景的效果產生積極影響。Babylon 提供多種類型的過程化紋理(木質、磚塊、火、云、草等)。我將要使用的是大理石紋理。
在創建保齡球的網格后,添加以下代碼行會讓保齡球變成綠色的大理石球(如圖 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?展示了我是如何添加邊線的,圖 14?展示了在我添加貼花紙后保齡球球道的外觀,以及在我將過程化紋理(磚塊和草)用作材料后地板和球槽的外觀。
圖 13:添加邊線貼花紙
~~~
// 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](http://bit.ly/1MEkNRo)),了解全部觸發器和操作。
我將使用操作管理器控制保齡球并重置場景。我將在本教程的第 2 部分中添加這些操作。
## 使用外部資源
我已使用 Babylon.js 的內部函數創建了所需的網格。大多數情況下,這是不夠的。Babylon.js 提供了很多網格(從球體和盒子到復雜的帶狀物),但創建復雜的模型是很難的,如人、Web 版 Doom 中的武器或 Space Invaders 克隆中的宇宙飛船。
Babylon.js 為很多知名的 3D 工具(如 Blender 和 3D-Studio)提供了導出程序插件。您也可以從出色的 Clara.io 中導出您的模型,然后下載 .babylon 文件。
Babylon.js 使用自己的文件格式,這種格式可以包含整個場景,包括網格、照相機、光、動畫、幾何體和其他信息。因此,如果您愿意,可以將 Blender 僅用于模擬整個場景。您還可以導入單個網格。
不過,這并不在本教程的范圍之內。對于本文,我只想展示如何只使用 Babylon.js 創建簡單的游戲。
## 下一步是什么?
我已跳過 Babylon.js 中集成的許多功能。它具有大量功能,我強烈建議您查看園地 ([babylonjs-playground.com](http://babylonjs-playground.com/))、文檔頁 ([doc.babylonjs.com](http://doc.babylonjs.com/)) 和 Babylon.js 主頁 ([babylonjs.com](http://babylonjs.com/)),看看如何開創無限可能。如果您覺得本教程的任何部分比較難懂,請聯系我或十分活躍的 Babylon.js HTML5 游戲開發論壇 ([bit.ly/1GmUyzq](http://bit.ly/1GmUyzq)) 上的任何一位 Babylon.js 大神。
在下一篇文章中,我將創建實際的游戲,即添加物理特性和碰撞檢測、擲球功能、音頻等。
* * *
Raanan Weber?*既是一名 IT 顧問、完整堆棧開發者,也是一名丈夫和父親。空閑時,他為 Babylon.js 和其他開放源代碼項目獻計獻策。您可以閱讀他的博客 ([blog.raananweber.com](http://blog.raananweber.com/))。*
- 介紹
- Visual Studio - 用于 Web 開發的新式工具: Grunt 和 Gulp
- 新員工 - 放長錢釣大魚
- Microsoft Azure - Azure Service Fabric 和微服務體系結構
- 數據點 - Aurelia 與 DocumentDB 結合: 結合之旅(第 2 部分)
- 游戲開發 - Babylon.js: 構建 Web 基本游戲
- 測試運行 - 面向 .NET 開發者的 Spark 簡介
- Xamarin - 使用 Xamarin.Forms 構建跨平臺用戶體驗
- 孜孜不倦的程序員 - 如何成為 MEAN: 快速輸入
- Microsoft Azure - Azure、Web API 和 Redis 如何有助于加快數據交付
- 必備 .NET - 設計 C# 7
- 新式應用 - 需要了解的 Windows 10 應用開發概念
- 別讓我打開話匣子 - 重構高等教育
- 編者注 - 再見 Kenny