Cum să construiești un joc de realitate virtuală multiplayer în timp real (Partea 1)
Publicat: 2022-03-10În această serie de tutoriale, vom construi un joc de realitate virtuală multiplayer bazat pe web, în care jucătorii vor trebui să colaboreze pentru a rezolva un puzzle. Vom folosi A-Frame pentru modelarea VR, MirrorVR pentru sincronizarea în timp real între dispozitive și A-Frame Low Poly pentru estetica low-poli. La sfârșitul acestui tutorial, veți avea o demonstrație online complet funcțională pe care o poate juca oricine.
Fiecare pereche de jucători primește un inel de globuri. Scopul este de a „porni” toate globurile, unde un glob este „pornit” dacă este ridicat și luminos. Un orb este „off” dacă este mai jos și slab. Cu toate acestea, anumite globuri „dominante” își afectează vecinii: dacă schimbă starea, vecinii săi schimbă și starea. Doar jucătorul 2 poate controla globurile dominante, în timp ce doar jucătorul 1 poate controla globurile nedominante. Acest lucru îi obligă pe ambii jucători să colaboreze pentru a rezolva puzzle-ul. În această primă parte a tutorialului, vom construi mediul și vom adăuga elementele de design pentru jocul nostru VR.
Cei șapte pași din acest tutorial sunt grupați în trei secțiuni:
- Configurarea scenei (Pașii 1–2)
- Crearea globurilor (Pașii 3–5)
- Efectuarea Orbs interactive (Pașii 6-7)
Această primă parte se va încheia cu un orb pe care se poate face clic care se pornește și se oprește (așa cum este imaginea de mai jos). Veți folosi A-Frame VR și mai multe extensii A-Frame.
Configurarea Scenei
1. Să mergem cu o scenă de bază
Pentru a începe, să aruncăm o privire la modul în care putem configura o scenă simplă cu un teren:
Primele trei instrucțiuni de mai jos sunt extrase din articolul meu anterior. Veți începe prin a configura un site web cu o singură pagină HTML statică. Acest lucru vă permite să codificați de pe desktop și să îl implementați automat pe web. Site-ul web implementat poate fi apoi încărcat pe telefonul mobil și plasat într-o cască VR. În mod alternativ, site-ul web implementat poate fi încărcat de o cască VR autonomă.
Începeți prin a naviga la glitch.com. Apoi, faceți următoarele:
- Faceți clic pe „Proiect nou” în dreapta sus,
- Faceți clic pe „hello-webpage” în meniul drop-down,
- Apoi, faceți clic pe index.html în bara laterală din stânga. Ne vom referi la asta drept „editorul tău”.
Acum ar trebui să vedeți următorul ecran Glitch cu un fișier HTML implicit.
Ca și în tutorialul legat de mai sus, începeți prin a șterge tot codul existent din fișierul index.html curent. Apoi, tastați următoarele pentru un proiect webVR de bază, folosind A-Frame VR. Acest lucru creează o scenă goală utilizând iluminarea și camera implicite 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>
Ridicați camera la înălțimea în picioare. Conform recomandărilor A-Frame VR (problema Github), împachetați camera cu o nouă entitate și mutați entitatea părinte în loc de camera direct. Între etichetele a-scene
pe rândurile 8 și 9, adăugați următoarele.
<!-- Camera! --> <a-entity position="0 3 0"> <a-camera wasd-controls look-controls></a-camera> </a-entity>
Apoi, adăugați o casetă mare pentru a indica pământul, folosind a-box
. Plasați-l direct sub camera dvs. din instrucțiunile anterioare.
<!-- Action! --> <a-box shadow width="75" height="0.1" depth="75" position="0 -1 0" color="#222"></a-box>
Fișierul dvs. index.html ar trebui acum să se potrivească exact cu următoarele. Puteți găsi codul sursă complet aici, pe 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>
Aceasta se încheie configurarea. În continuare, vom personaliza iluminarea pentru o atmosferă mai misterioasă.
2. Adăugați atmosferă
În acest pas, vom configura ceața și iluminarea personalizată.
Adăugați o ceață, care va întuneca obiectele aflate la distanță pentru noi. Modificați eticheta a-scene
pe linia 8. Aici, vom adăuga o ceață întunecată care ascunde rapid marginile pământului, dând efectul unui orizont îndepărtat.
<a-scene fog="type: linear; color: #111; near:10; far:15"></a-scene>
Gri închis #111
se estompează liniar de la o distanță de 10 la o distanță de 15. Toate obiectele aflate la mai mult de 15 unități sunt complet ascunse și toate obiectele aflate la mai puțin de 10 unități sunt complet vizibile. Orice obiect între ele este parțial ascuns.
Adăugați o lumină ambientală pentru a lumina obiectele din joc și lumină unidirecțională pentru a accentua suprafețele reflectorizante pe care le veți adăuga mai târziu. Plasați-l direct după eticheta a-scene
pe care ați modificat-o în instrucțiunea anterioară.
<!-- 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>
Direct sub lumini din instrucțiunile anterioare, adăugați un cer întunecat. Observați că gri închis #111
se potrivește cu cea din ceața îndepărtată.
<a-sky color="#111"></a-sky>
Aceasta încheie modificări de bază ale stării de spirit și, mai larg, configurarea scenei. Verificați dacă codul dvs. se potrivește exact cu codul sursă pentru Pasul 2 de pe Github. În continuare, vom adăuga un glob low-poly și vom începe să personalizăm estetica globului.
Crearea Orbs
3. Creați un Orb Low-Poly
În acest pas, vom crea un glob rotativ, reflectorizant, așa cum este imaginea de mai jos. Globul este compus din două sfere stilizate low-poli cu câteva trucuri pentru a sugera material reflectorizant.
Începeți prin a importa biblioteca low-poly din eticheta head
. Introduceți următoarele între rândurile 4 și 5.
<script src="https://cdn.jsdelivr.net/gh/alvinwan/[email protected]/dist/aframe-low-poly.min.js"></script>
Creați un carusel, un ambalaj și un container orb. carousel
va conține mai multe globuri, wrapper
ne va permite să rotim toate globurile în jurul unei axe centrale fără a roti fiecare glob individual, iar container
va conține - după cum sugerează și numele - toate componentele globului.
<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>
În interiorul recipientului globului, adăugați globul în sine: o sferă este ușor translucidă și decalată, iar cealaltă este complet solidă. Cele două combinate imită suprafețele reflectorizante.
<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>
În cele din urmă, rotiți sfera la nesfârșit adăugând următoarea etichetă a-animation
imediat după lp-sphere
interiorul entității .orb
în ultima instrucțiune.
<a-animation attribute="rotation" repeat="indefinite" from="0 0 0" to="0 360 0" dur="5000"></a-animation>
Codul dvs. sursă pentru ambalajele orb și orb-ul în sine ar trebui să se potrivească exact cu următoarele.
<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>
Verificați dacă codul dvs. sursă se potrivește cu codul sursă complet pentru pasul 3 pe Github. Previzualizarea dvs. ar trebui să se potrivească acum cu următoarele.
În continuare, vom adăuga mai multă lumină globului pentru o nuanță aurie.
4. Luminează Orb
În acest pas, vom adăuga două lumini, una colorată și una albă. Acest lucru produce următorul efect.
Începeți prin a adăuga lumina albă pentru a ilumina obiectul de jos. Vom folosi o lumină punctuală. Direct înainte de #orb0
, dar în cadrul #container-orb0
, adăugați următorul punct luminos de compensare.
<a-entity position="-2 -1 0"> <a-light distance="8" type="point" color="#FFF" intensity="0.8"></a-light> </a-entity>
În previzualizarea dvs., veți vedea următoarele.
În mod implicit, luminile nu se diminuează cu distanța. Adăugând distance="8"
, ne asigurăm că lumina scade complet cu o distanță de 8 unități, pentru a împiedica lumina punctuală să ilumineze întreaga scenă. Apoi, adăugați lumina aurie. Adăugați următoarele direct deasupra ultimei lumini.
<a-light class="light-orb" distance="8" type="point" color="#f90" intensity="1"></a-light>
Verificați dacă codul dvs. se potrivește exact cu codul sursă pentru pasul 4. Previzualizarea dvs. se va potrivi acum cu următoarele.
Apoi, veți face modificarea estetică finală a globului și veți adăuga inele rotative.
5. Adăugați inele
În acest pas, veți produce globul final, așa cum se arată mai jos.
Adăugați un inel în #container-orb0
direct înainte de #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>
Observați că inelul în sine nu conține culoare, deoarece culoarea va fi impregnată de lumina punctuală în pasul anterior. În plus, material="side:double"
este important deoarece, fără el, partea din spate a inelului nu ar fi redată; aceasta înseamnă că inelul ar dispărea pentru jumătate din rotație.
Cu toate acestea, previzualizarea doar cu codul de mai sus nu va arăta diferit. Acest lucru se datorează faptului că inelul este în prezent perpendicular pe ecran. Astfel, doar „partea” inelului (care are 0 grosime) este vizibilă. Plasați următoarea animație între etichetele a-ring
din instrucțiunea anterioară.
<a-animation attribute="rotation" easing="linear" repeat="indefinite" from="0 0 0" to="0 360 0" dur="8000"></a-animation>
Previzualizarea dvs. ar trebui să se potrivească acum cu următoarele:
Creați un număr variabil de inele cu diferite axe de rotație, viteze și dimensiuni. Puteți folosi următoarele exemple de inele. Orice inele noi ar trebui să fie plasate sub ultimul 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>
Previzualizarea dvs. se va potrivi acum cu următoarele.
Verificați dacă codul dvs. se potrivește cu codul sursă pentru pasul 5 pe Github. Aceasta încheie decorul pentru glob. Odată cu orb-ul terminat, vom adăuga în continuare interactivitate orb-ului. În pasul următor, vom adăuga în mod specific un cursor vizibil cu o animație de clic atunci când îndreptăm spre obiecte pe care se poate face clic.
Facerea Orbs interactiv
6. Adăugați un cursor
În acest pas, vom adăuga un cursor alb care poate declanșa obiecte pe care se poate face clic. Cursorul este ilustrat mai jos.
În eticheta a-camera
, adăugați următoarea entitate. Atributul fuse
permite acestei entități abilitatea de a declanșa evenimente de clic. Atributul raycaster
determină cât de des și cât de departe se verifică obiectele pe care se poate face clic. Atributul objects
acceptă un selector pentru a determina ce entități se pot face clic. În acest caz, toate obiectele din clasa pe care se poate face clickable
sunt pe care se poate face clic.
<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>
Apoi, adăugați animația cursorului și un inel suplimentar pentru estetică. Plasați următoarele în interiorul obiectului cursor entitate de mai sus. Aceasta adaugă animație obiectului cursor, astfel încât clicurile să fie vizibile.
<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>
Apoi, adăugați clasa pe care se clickable
la #orb0
pentru a se potrivi cu următoarele.
<a-entity class="orb clickable" data->
Verificați dacă codul dvs. se potrivește cu codul sursă pentru Pasul 6 pe Github. În previzualizare, trageți cursorul de pe ele pe orb pentru a vedea animația de clic în acțiune. Aceasta este imaginea de mai jos.
Rețineți că atributul pe care se poate face clic a fost adăugat la orb în sine și nu la containerul orb. Acest lucru este pentru a preveni inelele să devină obiecte pe care se poate face clic. În acest fel, utilizatorul trebuie să facă clic pe sferele care alcătuiesc orbul în sine.
În pasul nostru final pentru această parte, veți adăuga animație pentru a controla stările de pornire și oprire pentru orb.
7. Adăugați State Orb
În acest pas, veți anima globul în și din starea oprită la clic. Aceasta este imaginea de mai jos.
Pentru a începe, vei micșora și vei coborî globul la pământ. Adăugați etichete a-animation
la #container-orb0
imediat după #orb0
. Ambele animații sunt declanșate printr-un clic și au aceeași funcție ease-elastic
pentru o ușoară săritură.
<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>
Pentru a sublinia și mai mult starea oprită, vom elimina lumina punctului de aur când globul este stins. Cu toate acestea, luminile globului sunt plasate în afara obiectului globului. Astfel, evenimentul clic nu este transmis luminilor atunci când se face clic pe orb. Pentru a evita această problemă, vom folosi ceva Javascript ușor pentru a transmite evenimentul de clic la lumină. Plasați următoarea etichetă de animație în #light-orb0
. Lumina este declanșată de un eveniment de switch
personalizat.
<a-animation class="animation-intensity" begin="switch" attribute="intensity" from="0" to="1" direction="alternate"></a-animation>
Apoi, adăugați următorul ascultător de evenimente clic la #container-orb0
. Acest lucru va transmite clicurile către luminile orb.
<a-entity ...>
Verificați dacă codul dvs. se potrivește cu codul sursă pentru Pasul 7 pe Github. În cele din urmă, trageți în sus previzualizarea și mutați cursorul pe și în afara orbului pentru a comuta între stările dezactivate și activate. Aceasta este imaginea de mai jos.
Aceasta încheie interactivitatea globului. Jucătorul poate acum să pornească și să dezactiveze orburile după bunul plac, cu stări de activare și dezactivare autoexplicative.
Concluzie
În acest tutorial, ați creat un orb simplu cu stări pornit și oprit, care poate fi comutat printr-un clic de cursor compatibil cu căștile VR. Cu o serie de tehnici de iluminare și animații diferite, ați reușit să distingeți între cele două stări. Aceasta încheie elementele de proiectare a realității virtuale pentru sfere. În următoarea parte a tutorialului, vom popula globurile în mod dinamic, vom adăuga mecanisme de joc și vom configura un protocol de comunicare între o pereche de jucători.