如何構建實時多人虛擬現實遊戲(第 1 部分)

已發表: 2022-03-10
快速總結 ↬虛擬現實是一種用於探索內容的全新沉浸式媒體,無論該內容是電影 ( Life of Pi )、遊戲 ( Beat Saber ) 還是社交體驗(如Ready Player One中所述)。 儘管它很新穎,但 VR 並不需要完全不同的工具集來設計——我們用於網頁遊戲開發、3D 建模和其他工具的相同工具仍然適用。 本教程利用您對 Web 開發的熟悉程度來開始 VR 開發。

在本教程系列中,我們將構建一個基於網絡的多人虛擬現實遊戲,玩家需要在其中協作來解決難題。 我們將使用 A-Frame 進行 VR 建模,使用 MirrorVR 進行跨設備實時同步,使用 A-Frame Low Poly 進行低多邊形美學。 在本教程結束時,您將擁有一個功能齊全的在線演示,任何人都可以玩。

每對玩家都獲得一個圓環。 目標是“打開”所有球體,如果球體升高且明亮,則該球體“打開”。 如果球體較低且昏暗,則該球體“關閉”。 然而,某些“主導”球體會影響它們的鄰居:如果它切換狀態,它的鄰居也會切換狀態。 只有玩家 2 可以控制主導球體,而只有玩家 1 可以控制非主導球體。 這迫使雙方玩家合作解決難題。 在教程的第一部分,我們將為我們的 VR 遊戲構建環境並添加設計元素。

本教程中的七個步驟分為三個部分:

  1. 設置場景(步驟 1-2)
  2. 創建球體(步驟 3-5)
  3. 使球體互動(步驟 6-7)
跳躍後更多! 繼續往下看↓

第一部分將以打開和關閉的可點擊球體結束(如下圖所示)。 您將使用 A-Frame VR 和幾個 A-Frame 擴展。

(大預覽)

設置場景

1. 讓我們來看一個基本場景

首先,讓我們看看如何設置一個帶地面的簡單場景:

創建一個簡單的場景
創建一個簡單的場景(大預覽)

下面的前三個說明摘自我之前的文章。 您將首先建立一個具有單個靜態 HTML 頁面的網站。 這允許您從桌面編寫代碼並自動部署到 Web。 然後可以將部署的網站加載到您的手機上並放置在 VR 耳機中。 或者,部署的網站可以由獨立的 VR 耳機加載。

通過導航到 glitch.com 開始。 然後,執行以下操作:

  1. 點擊右上角的“新建項目”,
  2. 點擊下拉菜單中的“hello-webpage”,
  3. 接下來,單擊左側邊欄中的index.html 。 我們將其稱為您的“編輯器”。

您現在應該會看到以下帶有默認 HTML 文件的故障屏幕。

故障項目:index.html 文件
故障項目:index.html 文件(大預覽)

與上面的鏈接教程一樣,首先刪除當前index.html文件中的所有現有代碼。 然後,使用 A-Frame VR 為基本的 webVR 項目鍵入以下內容。 這將使用 A-Frame 的默認照明和相機創建一個空場景。

 <!DOCTYPE html> <html> <head> <title>Lightful</title> <script src="https://aframe.io/releases/0.8.0/aframe.min.js"></script> </head> <body> <a-scene> </a-scene> </body> </html>

將相機升高到站立高度。 根據 A-Frame VR 建議(Github 問題),用新實體包裝相機並移動父實體而不是直接移動相機。 在第 8 行和第 9 行的a-scene標籤之間,添加以下內容。

 <!-- Camera! --> <a-entity position="0 3 0"> <a-camera wasd-controls look-controls></a-camera> </a-entity>

接下來,使用a-box添加一個大框來表示地面。 按照前面的說明將其直接放在相機下方。

 <!-- Action! --> <a-box shadow width="75" height="0.1" depth="75" position="0 -1 0" color="#222"></a-box>

您的index.html文件現在應該與以下內容完全匹配。 你可以在 Github 上找到完整的源代碼。

 <html> <head> <title>Lightful</title> <script src="https://aframe.io/releases/0.8.0/aframe.min.js"></script> </head> <body> <a-scene> <!-- Camera! --> <a-entity position="0 3 0"> <a-camera wasd-controls look-controls></a-camera> </a-entity> <!-- Action! --> <a-box shadow width="75" height="0.1" depth="75" position="0 -1 0" color="#222"></a-box> </a-scene> </body> </html>

設置到此結束。 接下來,我們將定制燈光,營造更神秘的氛圍。

2.添加氣氛

在這一步中,我們將設置霧和自定義照明。

一個帶有黑暗情緒的簡單場景的預覽
一個帶有黑暗情緒的簡單場景的預覽(大預覽)

添加霧,它會模糊我們遠處的物體。 修改第 8 行的a-scene標籤。在這裡,我們將添加一個快速遮蓋地面邊緣的黑霧,營造出遙遠地平線的效果。

 <a-scene fog="type: linear; color: #111; near:10; far:15"></a-scene>

深灰色#111從 10 到 15 的距離呈線性淡入。所有超過 15 個單位的物體都完全被遮蔽,所有小於 10 個單位的物體都完全可見。 中間的任何物體都被部分遮擋。

添加一個環境光以照亮遊戲中的對象,並添加一個單向光以突出您稍後將添加的反射表面。 將其直接放在您在上一條指令中修改的a-scene標記之後。

 <!-- Lights! --> <a-light type="directional" castshadow="true" intensity="0.5" color="#FFF" position="2 5 0"></a-light> <a-light intensity="0.1" type="ambient" position="1 1 1" color="#FFF"></a-light>

在上一個指令中的燈光正下方,添加一個黑暗的天空。 請注意深灰色#111與遠處霧的顏色相匹配。

 <a-sky color="#111"></a-sky>

這結束了對情緒的基本修改以及更廣泛的場景設置。 檢查您的代碼是否與 Github 上第 2 步的源代碼完全匹配。 接下來,我們將添加一個低多邊形球體並開始自定義球體的美學。

創建球體

3. 創建一個低聚球體

在這一步中,我們將創建一個旋轉的反射球,如下圖所示。 該球體由兩個程式化的低多邊形球體組成,並帶有一些提示反射材料的技巧。

旋轉反射球
(大預覽)

首先在你的head標籤中導入低多邊形庫。 在第 4 行和第 5 行之間插入以下內容。

 <script src="https://cdn.jsdelivr.net/gh/alvinwan/[email protected]/dist/aframe-low-poly.min.js"></script>

創建一個輪播、包裝器和球體容器。 carousel將包含多個球體, wrapper將允許我們圍繞中心軸旋轉所有球體,而無需單獨旋轉每個球體,並且container (顧名思義)將包含所有球體組件。

 <a-entity> <a-entity rotation="0 90 0" class="wrapper" position="0 0 0"> <a-entity class="container" position="8 3 0" scale="1 1 1"> <!-- place orb here --> </a-entity> </a-entity> </a-entity>

在球體容器內,添加球體本身:一個球體略微半透明並偏移,另一個球體完全實心。 這兩個組合模擬反射表面。

 <a-entity class="orb" data-> <lp-sphere seed="0" shadow max-amplitude="1 1 1" position="-0.5 0 -0.5"></lp-sphere> <lp-sphere seed="0" shadow max-amplitude="1 1 1" rotation="0 45 45" opacity="0.5" position="-0.5 0 -0.5"></lp-sphere> </a-entity>

最後,通過在最後一條指令中的.orb實體內的lp-sphere之後立即添加以下a-animation標籤,無限期地旋轉球體。

 <a-animation attribute="rotation" repeat="indefinite" from="0 0 0" to="0 360 0" dur="5000"></a-animation>

您的 orb 包裝器和 orb 本身的源代碼應與以下內容完全匹配。

 <a-entity> <a-entity rotation="0 90 0" class="wrapper" position="0 0 0"> <a-entity class="container" position="8 3 0" scale="1 1 1"> <a-entity class="orb" data-> <lp-sphere seed="0" shadow max-amplitude="1 1 1" position="-0.5 0 -0.5"></lp-sphere> <lp-sphere seed="0" shadow max-amplitude="1 1 1" rotation="0 45 45" opacity="0.5" position="-0.5 0 -0.5"></lp-sphere> <a-animation attribute="rotation" repeat="indefinite" from="0 0 0" to="0 360 0" dur="5000"></a-animation> </a-entity> </a-entity> </a-entity> </a-entity>

檢查您的源代碼是否與 Github 上第 3 步的完整源代碼匹配。 您的預覽現在應該與以下內容匹配。

旋轉反射球
(大預覽)

接下來,我們將為球體添加更多照明以獲得金色。

4.點亮球體

在這一步中,我們將添加兩盞燈,一盞彩色燈和一盞白色燈。 這會產生以下效果。

用點光源點亮的球體
(大預覽)

首先添加白光以從下方照亮對象。 我們將使用點光源。 直接在#orb0之前但在#container-orb0內,添加以下偏移點光源。

 <a-entity position="-2 -1 0"> <a-light distance="8" type="point" color="#FFF" intensity="0.8"></a-light> </a-entity>

在您的預覽中,您將看到以下內容。

用白點光源點亮的球體
(大預覽)

默認情況下,燈光不會隨距離衰減。 通過添加distance="8" ,我們確保光在 8 個單位的距離內完全衰減,以防止點光照亮整個場景。 接下來,添加金光。 在最後一個燈的正上方添加以下內容。

 <a-light class="light-orb" distance="8" type="point" color="#f90" intensity="1"></a-light>

檢查您的代碼是否與第 4 步的源代碼完全匹配。 您的預覽現在將與以下內容匹配。

用點光源點亮的球體
(大預覽)

接下來,您將對球體進行最終的美學修改並添加旋轉環。

5.添加戒指

在此步驟中,您將生成最終的球體,如下圖所示。

帶有多個環的金色球體
(大預覽)

在 #orb0 之前直接在#orb0 #container-orb0中添加一個環。

 <a-ring color="#fff" material="side:double" position="0 0.5 0" radius-inner="1.9" radius-outer="2" opacity="0.25"></a-ring>

請注意,環本身不包含顏色,因為顏色將被上一步中的點光充滿。 此外, material="side:double"很重要,因為沒有它,戒指的背面就不會被渲染; 這意味著環會在其旋轉的一半時間內消失。

但是,僅包含上述代碼的預覽看起來並沒有什麼不同。 這是因為環當前垂直於屏幕。 因此,只有環的“側面”(厚度為 0)是可見的。 將以下動畫放置在上一條指令中的a-ring標籤之間。

 <a-animation attribute="rotation" easing="linear" repeat="indefinite" from="0 0 0" to="0 360 0" dur="8000"></a-animation>

您的預覽現在應該與以下內容匹配:

帶環的金球
(大預覽)

創建具有不同旋轉軸、速度和大小的可變數量的環。 您可以使用以下示例環。 任何新的環都應該放在最後a-ring下面。

 <a-ring color="#fff" material="side:double" position="0 0.5 0" radius-inner="2.4" radius-outer="2.5" opacity="0.25"> <a-animation attribute="rotation" easing="linear" repeat="indefinite" from="0 45 0" to="360 45 0" dur="8000"></a-animation> </a-ring> <a-ring color="#fff" material="side:double" position="0 0.5 0" radius-inner="1.4" radius-outer="1.5" opacity="0.25"> <a-animation attribute="rotation" easing="linear" repeat="indefinite" from="0 -60 0" to="-360 -60 0" dur="3000"></a-animation> </a-ring>

您的預覽現在將與以下內容匹配。

帶有多個環的金色球體
(大預覽)

檢查您的代碼是否與 Github 上第 5 步的源代碼匹配。 球體的裝飾到此結束。 完成球體後,我們接下來將向球體添加交互性。 在下一步中,我們將專門添加一個可見光標,當指向可點擊對象時帶有點擊動畫。

使球體互動

6.添加光標

在這一步中,我們將添加一個可以觸發可點擊對象的白色光標。 光標如下圖所示。

點擊球體
(大預覽)

在您a-camera標籤中,添加以下實體。 fuse屬性允許該實體觸發點擊事件。 raycaster屬性決定了檢查可點擊對象的頻率和距離。 objects屬性接受一個選擇器來確定哪些實體是可點擊的。 在這種情況下,所有clickable點擊類的對像都是可點擊的。

 <a-entity cursor="fuse: true; fuseTimeout: 250" position="0 0 -1" geometry="primitive: ring; radiusInner: 0.03; radiusOuter: 0.04" material="color: white; shader: flat; opacity: 0.5" scale="0.5 0.5 0.5" raycaster="far: 20; interval: 1000; objects: .clickable"> <!-- Place cursor animation here --> </a-entity>

接下來,為美觀添加光標動畫和額外的環。 將以下內容放在上面的實體光標對像中。 這將動畫添加到光標對象,以便點擊可見。

 <a-circle radius="0.01" color="#FFF" opacity="0.5" material="shader: flat"></a-circle> <a-animation begin="fusing" easing="ease-in" attribute="scale" fill="backwards" from="1 1 1" to="0.2 0.2 0.2" dur="250"></a-animation>

接下來,將clickable類添加到#orb0以匹配以下內容。

 <a-entity class="orb clickable" data->

檢查您的代碼是否與 Github 上第 6 步的源代碼匹配。 在您的預覽中,將光標從它們上拖到球體上,以查看實際的點擊動畫。 如下圖所示。

點擊球體
(大預覽)

請注意,可點擊屬性已添加到球體本身,而不是球體容器。 這是為了防止環變成可點擊的對象。 這樣,用戶必須單擊構成球體本身的球體。

在這部分的最後一步中,您將添加動畫來控制球體的開啟和關閉狀態。

7.添加球體狀態

在此步驟中,您將在單擊時將球體設置為動畫進入和退出關閉狀態。 如下圖所示。

響應點擊的交互式球體
(大預覽)

首先,您將縮小球體並將其降低到地面。 在 #orb0 之後將a-animation標籤添加到#container-orb0 #orb0 。 兩個動畫都是通過單擊觸發的,並共享相同的緩動函數ease-elastic以實現輕微反彈。

 <a-animation class="animation-scale" easing="ease-elastic" begin="click" attribute="scale" from="0.5 0.5 0.5" to="1 1 1" direction="alternate" dur="2000"></a-animation> <a-animation class="animation-position" easing="ease-elastic" begin="click" attribute="position" from="8 0.5 0" to="8 3 0" direction="alternate" dur="2000"></a-animation>

為了進一步強調關閉狀態,我們將在球體關閉時移除黃金點光源。 但是,球體的燈光放置在球體對象之外。 因此,當點擊球體時,點擊事件不會傳遞給燈光。 為了規避這個問題,我們將使用一些輕量級的 Javascript 將點擊事件傳遞給燈光。 將以下動畫標籤放在#light-orb0中。 燈光由自定義switch事件觸發。

 <a-animation class="animation-intensity" begin="switch" attribute="intensity" from="0" to="1" direction="alternate"></a-animation>

接下來,將以下單擊事件偵聽器添加到#container-orb0 。 這會將點擊中繼到球燈。

 <a-entity ...>

檢查您的代碼是否與 Github 上第 7 步的源代碼匹配。 最後,拉起您的預覽,然後將光標移開和移出球體以在關閉和打開狀態之間切換。 如下圖所示。

響應點擊的交互式球體
(大預覽)

這結束了球體的交互性。 玩家現在可以隨意打開和關閉球體,具有不言自明的打開和關閉狀態。

結論

在本教程中,您構建了一個具有開啟和關閉狀態的簡單球體,可以通過 VR 耳機友好的光標單擊來切換。 通過多種不同的照明技術和動畫,您可以區分這兩種狀態。 球體的虛擬現實設計元素到此結束。 在本教程的下一部分中,我們將動態填充球體,添加遊戲機制,並設置一對玩家之間的通信協議。