8 る 2015

第 30 卷,第 8 期

本文章是由機器翻譯。

遊戲開發-網頁遊戲 3D 簡介

Michael Oneppo |到 2015 2015年 8 月

將第三維度添加到一個遊戲,給生活真正帶來。你可以從任何角度來看環顧四周,看到每個角度的物體或場景。但如何能你把這事在幕後?在這個系列的文章,我會走過使 3D 遊戲的步驟,給你展示如何庫如 three.js 可以説明您實現豐富、 3D 環境變得如此受歡迎,在 Web 上。在第一部分中,我會保持它的簡單,著力建設坪遊戲在"Web 遊戲在一小時"首次描述 3D 版本 (msdn.microsoft.com/magazine/dn913185)。

3D 幻覺的

任何 3D 圖形渲染其袖子做了令人驚訝。人類不能真正看到 3D 尺寸中 — — 特別是在電腦監視器上。3D 繪圖的整個目標是生成,或呈現,3D 場景的描述中 2D 圖像上。當你添加一個第三維度以獲得更多的身臨其境的和現實的場景時,你不得不扔掉一些資料來從特定的角度得到的合成圖像。這一概念被稱為投影。是什麼使得 3D 圖形工作,基本的 3D 場景中所示的基本要素圖 1

簡單的 3D 場景
圖 1 簡單的 3D 場景

在此場景中,Z 軸消退向上和向後。如果我想把它在螢幕上,我可以只下降 Z 資訊從每個物件作為簡單和有效的方式,到專案的 3D 場景,如中所示圖 2

壓扁 3D 場景
圖 2 壓扁 3D 場景

正如你所看到的這並不是完全的光環。為超級寫實主義,3D 場景需要三樣東西 — — 適當的攝像機投影、 幾何和網底。當我作為決鬥遊戲 3D 重建坪遊戲,我將介紹每個這些概念。

開始使用

首先,我會設置 three.js 圖書館。這是一個相當快的配置,幾乎你與 three.js 所做的一切發生在 JavaScript 中。這裡是你需要的 HTML 代碼:

<html>
  <head>
    <title>Ping!</title>
    <script src=
      "//cdnjs.cloudflare.com/ajax/libs/three.js/r69/three.min.js"></script>
    <script src="ping3d.js"></script>
  </head>
  <body>
  </body>
</html>

在 JavaScript 檔 ping3d.js,我要去設立 three.js 提供一個簡單的場景。首先,我需要初始化 three.js 和其在繪圖畫布上添加頁面:

var scene = new THREE.Scene();
var renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );

現場正是這聽起來像 — — 描述我們的場景和內的所有物件的物件。渲染器也顯然被命名。當給定一個場景,渲染器會把它拖到螢幕。這看起來應該類似一些 2D 圖紙我描述在前面的文章,"網路遊戲中一小時,"系統"2D 繪圖技術和 Web 遊戲庫"(msdn.microsoft.com/magazine/dn948109) 和"2D 遊戲引擎網站"(msdn.microsoft.com/magazine/dn973016)。現在我需要向螢幕中添加一些元素。

Geometry

幾乎所有的 3D 圖形是由多邊形。甚至像一個球曲面近似成三角面逼近它的表面。組裝時,這些三角形的網格。這裡是如何將球添加到場景:

var geometry = new THREE.SphereGeometry(10);
var material = new THREE.BasicMaterial({color: 0xFF0000});
var mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);

此代碼會創建大量的三角形代表一個球體 ("幾何"變數)、 簡單的亮紅色材料 ("材料") 和網格物件 ("目")。然後它會將網格添加到現場。

三角形是 3D 圖形學的基本構造塊。為什麼會這樣?我會在本系列的下一篇文章中深入研究這個但兩個主要原因是構成了一個三角形的直線很容易就可以與工作,不能將一個三角形分成一個更基本的平面。圖形處理單元 (GPU) 在你的電腦或手機上有專門的硬體,可以快速將形狀與直線轉換為圖元。這是好的一部分,是什麼使高品質的 3D 圖形可能。

耀倰趙

我能通過任何幾何成三。網格的建構函式。這包括生成的幾何使自訂形狀或甚至資料從檔。平的遊戲,我想要的每個玩家的 3D 模型。因此,我已經在本練習中的三維建模程式中創建幾何的自由。它是非常容易使用的模型,而不是一個球體,three.js 為此提供了一個載入工具:

var jsonLoader = new THREE.JSONLoader();
jsonLoader.load('tank1.json', function (geometry) {
  var material = new THREE.BasicMaterial({color: 0xFF0000});
  var mesh = new THREE.Mesh(geometry, material);
  scene.add(mesh);
});

照相機

相機代表現場的觀點。它存儲的位置和角度的在遊戲內查看。更重要的是,相機代表如何現場變得扁平,如本文開頭所述。

在我的示例中,攝像機被安置了向下和向右。最終的圖像出現作為視圖從那個方向。然而,使用這種投射方法,無論物件距離有多遠,他們將留在最終圖像中的相同大小。這就被所謂的正交投影。這通常是用於與非現實視角像城市類比遊戲的遊戲。我真的想要實現的是要使物件看起來更小,因為他們已經遠去。

輸入透視投影:透視投影作為一座金字塔,從鏡頭延伸想像一台相機的視野。當位置映射到螢幕時,他們計算的基礎上兩側的金字塔的相對距離。使用此模型中,物件已經遠去,他們似乎收縮在現實生活。

值得慶倖的是,你不需要做這個的映射自己因為 three.js 會為你提供了一個物件,表示在現場攝像機 (和添加另一種是簡單的):

var camera = new THREE.PerspectiveCamera(
  75, window.innerWidth/window.innerHeight, 0.1, 1000 );

第一個參數是欄位的視圖,它指示多少角的距離在水準方向採取。第二個參數是的螢幕寬度和高度,您需要確保事情不壓扁,因為不是方形的螢幕比例。最後兩個參數定義的最近和最遠的距離,以顯示。什麼更接近或超出這些值並不是畫。現在在哪裡其實可以現場點。讓我們移動相機後挪一點來查看整個場景和開始繪圖:

camera.position.z = 50;
renderer.render(scene, camera);

材料和燈光

接下來,我會將球放在舞臺上,它還會彈:

var room = new THREE.BoxGeometry( 50, 30, 100 );
var material = new THREE.MeshPhongMaterial({
    side:  THREE.BackSide,
    map: THREE.ImageUtils.loadTexture('arena.png')
});
var model = new THREE.Mesh(room, material);
model.position.y = 15;
scene.add(model);

我正在做比只做框幾何不同的東西。我也在做一種材料。一種材料是一個定義的東西如何應反映在一個場景中的光。這將生成其整體的外觀。在這種情況下,我正在蓬材料,這是一個好的預設為有光澤的物件。我也到框,它是簡單 three.js 使用 loadTexture 函數中添加紋理。

此代碼的一個其他值得注意的方面是讀取的行:方:三。背面。 這將指示 three.js 畫只有內部雙方在盒面上,而不是外側。這給球反彈,而不是一個固體的盒子漂浮在空間的餘地。

我要是現在繪製場景,舞臺上不可見。它只是將畫黑色。這是因為材料定義如何做不得尚未對場景的光和光反射物件。Three.js 使得添加光線到場景簡單,如下所示:

this.lights = [];
this.lights[0] = new THREE.PointLight( 0x888888, 1, 300 );
this.lights[0].position.set( 0, 10, 40 );
scene.add( this.lights[0] );
this.lights[1] = new THREE.PointLight( 0x888888, 1, 300 );
this.lights[1].position.set( 0, 20, -40 );
scene.add( this.lights[1] );

現在如果我繪製場景,舞臺上將正確呈現。要更好的看法,我會設置相機位置運行代碼之前在舞臺上的一側看:

camera.up.copy(new THREE.Vector3(0,1,0));
camera.position.copy(new THREE.Vector3(0,17, -80));
camera.lookAt(new THREE.Vector3(0,0,40));

第一行設置向上的變數,只是告訴你的相機走哪條路是了。看看功能是否完全因為它的聲音 — — 它指出相機中的指定位置。

製作 3D 遊戲

現在,遊戲已經搬進三個維度,讓其他人應該是很容易的。然而,這場比賽就要結束有點更詳細比以前實現因為它組成的 3D,而不是二維物件。所以我會分手到單獨的檔,以使附加的代碼易於處理代碼。

我也會轉移到更傳統的建構函式模型 JavaScript 物件定義的樣式。為了證明這一點,我就可以包裝競技場框和燈到物件並放在一個檔中,如中所示圖 3

圖 3 的舞臺上的物件

function Arena(scene) {
  var room = new THREE.BoxGeometry( 50, 30, 100 );
  var material = new THREE.MeshPhongMaterial({
    side:  THREE.BackSide,
    map: THREE.ImageUtils.loadTexture('arena.png')
  });
  var model = new THREE.Mesh(room, material);
  model.position.y = 15;
  scene.add(model);
  this.lights = [];
  this.lights[0]= new THREE.PointLight( 0x888888, 1, 300 );
  this.lights[0].position.set( 0, 10, 40 );
  scene.add( this.lights[0] );
  this.lights[1]= new THREE.PointLight( 0x888888, 1, 300 );
  this.lights[1].position.set( 0, 20, -40 );
  scene.add( this.lights[1] );
}

如果我想要創建一個舞臺,我可以創建一個新的物件,使用此建構函式:

var arena = new Arena(scene);

接下來,我會讓一個球物件,可以在舞臺上蹦蹦跳跳。我知道如何使一個紅色的球在 three.js,所以我會將該代碼包裝到物件,以及:

function Ball(scene) {
  var mesh = new THREE.SphereGeometry(1.5, 10, 10);
  var material = new THREE.MeshPhongMaterial({
    color: 0xff0000,
    specular: 0x333333
  });
  var _model = new THREE.Mesh(mesh, material);
  _model.position.y = 10;
  scene.add(_model);
}

現在我將定義的彈跳球通過將功能添加到球物件,如中所示的基本物理圖 4

圖 4 球物件更新功能

// Create a private class variable and set it to some initial value.
var _velocity = new THREE.Vector3(40,0,40);
this.update = function(t) {
  // Apply a little gravity to the ball.
  _velocity.y -= 25 * t;
  // Move the ball according to its velocity
  var offset = _velocity.clone()
    .multiplyScalar(t);
  _model.position.add(offset);
  // Now bounce it off the walls and the floor.
  // Ignore the ends of the arena.
  if (_model.position.y - 1.5 <= 0) {
    _model.position.y = 1.5;
    _velocity.y *= -1;
  }
  if (_model.position.x - 1.5 <= -25) {
    _model.position.x = -23.5;
    _velocity.x *= -1;
  }
  if (_model.position.x + 1.5 >= 25) {
    _model.position.x = 23.5;
    _velocity.x *= -1;
  }
}

Three.js 需要你渲染場景,每一次使用 requestAnimationFrame。這應該是熟悉的模式:

var ball = new Ball(scene);
var Arena = new Arena(scene);
var render = function (time) {
  var t = (time - lastTime) / 1000.0;
  lastTime = time;
  ball.update(t);
  renderer.render(scene, camera);
  requestAnimationFrame( render );
}
requestAnimationFrame(render);

敬請期待

現在舞臺上有燈光,得天獨厚的相機和一個球蹦來蹦去現場。這是所有我要在這篇文章仲介紹。在下一篇文章中,我將解釋如何 3D 投影讓你的目標是用滑鼠的作品。我更詳細的說明紋理也能平滑動畫使用功能強大的庫,被稱為 tween.js。 在最後的這三篇文章,我會看看 three.js 引擎蓋,看如何,它實際上繪製這種高保真圖形。


Michael Oneppo 是一個創造性的技術專家和 Direct3D 團隊在微軟前程式經理。他最近的努力包括在技術工作,作為首席技術官非營利組織所有圖書館和探索在互動式電信節目中紐約大學碩士學位。

感謝以下技術專家對本文的審閱:Mohamed 阿明易卜拉欣