Come costruire un gioco di realtà virtuale multigiocatore in tempo reale (parte 1)

Pubblicato: 2022-03-10
Riassunto veloce ↬ La realtà virtuale è un nuovo mezzo immersivo per esplorare i contenuti, sia che si tratti di un film ( Life of Pi ), ​​di un gioco ( Beat Saber ) o di un'esperienza sociale (come illustrato in Ready Player One ). Nonostante la sua novità, la realtà virtuale non richiede un set di strumenti drasticamente diverso per la progettazione: gli stessi strumenti che utilizziamo per lo sviluppo di giochi Web, la modellazione 3D e altri sono ancora tutti applicabili. Questo tutorial sfrutta la tua familiarità con lo sviluppo web per iniziare con lo sviluppo della realtà virtuale.

In questa serie di tutorial, costruiremo un gioco di realtà virtuale multiplayer basato sul Web in cui i giocatori dovranno collaborare per risolvere un enigma. Useremo A-Frame per la modellazione VR, MirrorVR per la sincronizzazione in tempo reale tra dispositivi e A-Frame Low Poly per l'estetica a basso numero di poligoni. Alla fine di questo tutorial, avrai una demo online completamente funzionante a cui chiunque può giocare.

Ad ogni coppia di giocatori viene assegnato un anello di sfere. L'obiettivo è "accendere" tutte le sfere, dove una sfera è "accesa" se è elevata e luminosa. Una sfera è "spenta" se è più bassa e debole. Tuttavia, alcune sfere "dominanti" influiscono sui loro vicini: se cambia stato, anche i suoi vicini cambiano stato. Solo il giocatore 2 può controllare le sfere dominanti mentre solo il giocatore 1 può controllare le sfere non dominanti. Questo costringe entrambi i giocatori a collaborare per risolvere il puzzle. In questa prima parte del tutorial, costruiremo l'ambiente e aggiungeremo gli elementi di design per il nostro gioco VR.

I sette passaggi di questo tutorial sono raggruppati in tre sezioni:

  1. Impostazione della scena (punti 1–2)
  2. Creazione delle sfere (passaggi 3–5)
  3. Rendere le sfere interattive (passaggi 6–7)
Altro dopo il salto! Continua a leggere sotto ↓

Questa prima parte si concluderà con una sfera cliccabile che si accende e si spegne (come illustrato di seguito). Utilizzerai A-Frame VR e diverse estensioni A-Frame.

(Grande anteprima)

Allestimento della scena

1. Andiamo con una scena di base

Per iniziare, diamo un'occhiata a come possiamo impostare una scena semplice con un terreno:

Creazione di una scena semplice
Creazione di una scena semplice (Anteprima grande)

Le prime tre istruzioni di seguito sono estratte dal mio precedente articolo. Inizierai impostando un sito Web con una singola pagina HTML statica. Ciò consente di codificare dal desktop e distribuire automaticamente sul Web. Il sito Web distribuito può quindi essere caricato sul telefono cellulare e posizionato all'interno di un visore VR. In alternativa, il sito Web distribuito può essere caricato da un visore VR autonomo.

Inizia navigando su glitch.com. Quindi, procedi come segue:

  1. Clicca su “Nuovo Progetto” in alto a destra,
  2. Fare clic su "Hello-webpage" nel menu a discesa,
  3. Quindi, fai clic su index.html nella barra laterale di sinistra. Lo chiameremo "editore".

Ora dovresti vedere la seguente schermata Glitch con un file HTML predefinito.

Progetto glitch: il file index.html
Progetto Glitch: il file index.html (Anteprima grande)

Come con il tutorial collegato sopra, inizia eliminando tutto il codice esistente nel file index.html corrente. Quindi, digita quanto segue per un progetto webVR di base, utilizzando A-Frame VR. Questo crea una scena vuota utilizzando l'illuminazione e la fotocamera predefinite di 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>

Sollevare la fotocamera all'altezza in piedi. In base ai consigli di A-Frame VR (problema con Github), avvolgi la videocamera con una nuova entità e sposta direttamente l'entità padre anziché la videocamera. Tra i tag a-scene alle righe 8 e 9, aggiungi quanto segue.

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

Quindi, aggiungi una grande casella per denotare il terreno, usando a-box . Posizionalo direttamente sotto la tua fotocamera dalle istruzioni precedenti.

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

Il tuo file index.html ora dovrebbe corrispondere esattamente a quanto segue. Puoi trovare il codice sorgente completo qui, su 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>

Questo conclude l'installazione. Successivamente, personalizzeremo l'illuminazione per un'atmosfera più misteriosa.

2. Aggiungi atmosfera

In questo passaggio, imposteremo la nebbia e l'illuminazione personalizzata.

Un'anteprima di una scena semplice con uno stato d'animo oscuro
Un'anteprima di una scena semplice con uno stato d'animo cupo (Anteprima grande)

Aggiungi una nebbia, che oscurerà gli oggetti lontani per noi. Modifica il tag a a-scene sulla riga 8. Qui aggiungeremo una nebbia scura che oscura rapidamente i bordi del terreno, dando l'effetto di un orizzonte lontano.

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

Il grigio scuro #111 sfuma in modo lineare da una distanza di 10 a una distanza di 15. Tutti gli oggetti a più di 15 unità di distanza sono completamente oscurati e tutti gli oggetti a meno di 10 unità di distanza sono completamente visibili. Qualsiasi oggetto in mezzo è parzialmente oscurato.

Aggiungi una luce ambientale per schiarire gli oggetti di gioco e una luce unidirezionale per accentuare le superfici riflettenti che aggiungerai in seguito. Posizionalo direttamente dopo il tag a-scene che hai modificato nell'istruzione precedente.

 <!-- 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>

Direttamente sotto le luci dell'istruzione precedente, aggiungi un cielo scuro. Notare che il grigio scuro #111 corrisponde a quello della nebbia lontana.

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

Questo conclude le modifiche di base all'atmosfera e, più in generale, all'impostazione della scena. Verifica che il tuo codice corrisponda esattamente al codice sorgente per il passaggio 2 su Github. Successivamente, aggiungeremo una sfera a basso numero di poligoni e inizieremo a personalizzare l'estetica della sfera.

Creazione delle sfere

3. Crea una sfera a basso numero di poligoni

In questo passaggio, creeremo una sfera riflettente rotante come mostrato di seguito. Il globo è composto da due sfere stilizzate a basso numero di poligoni con alcuni accorgimenti per suggerire materiale riflettente.

Sfera rotante e riflettente
(Grande anteprima)

Inizia importando la libreria low-poly nel tag head . Inserisci quanto segue tra le righe 4 e 5.

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

Crea un carosello, un involucro e un contenitore per sfere. Il carousel conterrà più sfere, l' wrapper ci consentirà di ruotare tutte le sfere attorno a un asse centrale senza ruotare ciascuna sfera individualmente e il container , come suggerisce il nome, conterrà tutti i componenti delle sfere.

 <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>

All'interno del contenitore della sfera, aggiungi la sfera stessa: una sfera è leggermente traslucida e sfalsata e l'altra è completamente solida. Le due combinate imitano le superfici riflettenti.

 <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>

Infine, ruota la sfera indefinitamente aggiungendo il seguente tag a-animation subito dopo la lp-sphere all'interno dell'entità .orb nell'ultima istruzione.

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

Il tuo codice sorgente per i wrapper dell'orb e l'orb stesso dovrebbe corrispondere esattamente a quanto segue.

 <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 che il tuo codice sorgente corrisponda al codice sorgente completo per il passaggio 3 su Github. La tua anteprima ora dovrebbe corrispondere a quanto segue.

Sfera rotante e riflettente
(Grande anteprima)

Successivamente, aggiungeremo più illuminazione al globo per ottenere una tonalità dorata.

4. Illumina il globo

In questo passaggio aggiungeremo due luci, una colorata e una bianca. Questo produce il seguente effetto.

Globo illuminato con luci puntiformi
(Grande anteprima)

Inizia aggiungendo la luce bianca per illuminare l'oggetto dal basso. Useremo una luce puntiforme. Direttamente prima #orb0 ma all'interno di #container-orb0 , aggiungi il seguente punto luce offset.

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

Nella tua anteprima vedrai quanto segue.

Globo illuminato con punto luce bianco
(Grande anteprima)

Per impostazione predefinita, le luci non decadono con la distanza. Aggiungendo distance="8" , assicuriamo che la luce decada completamente con una distanza di 8 unità, per evitare che la luce puntiforme illumini l'intera scena. Quindi, aggiungi la luce dorata. Aggiungi quanto segue direttamente sopra l'ultima luce.

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

Verifica che il tuo codice corrisponda esattamente al codice sorgente per il passaggio 4. La tua anteprima ora corrisponderà a quanto segue.

Globo illuminato con luci puntiformi
(Grande anteprima)

Successivamente, apporterai la modifica estetica finale alla sfera e aggiungerai anelli rotanti.

5. Aggiungi anelli

In questo passaggio, produrrai la sfera finale, come illustrato di seguito.

Sfera dorata con più anelli
(Grande anteprima)

Aggiungi un anello in #container-orb0 direttamente prima #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>

Si noti che l'anello stesso non contiene colore, poiché il colore sarà imbevuto della luce puntiforme nel passaggio precedente. Inoltre, il material="side:double" è importante in quanto, senza di esso, il retro dell'anello non sarebbe reso; questo significa che l'anello scomparirebbe per metà della sua rotazione.

Tuttavia, l'anteprima con solo il codice precedente non avrà un aspetto diverso. Questo perché l'anello è attualmente perpendicolare allo schermo. Pertanto, è visibile solo il "lato" dell'anello (che ha uno spessore 0). Posiziona la seguente animazione tra i tag a a-ring nell'istruzione precedente.

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

La tua anteprima ora dovrebbe corrispondere a quanto segue:

Sfera dorata con anello
(Grande anteprima)

Crea un numero variabile di anelli con diversi assi di rotazione, velocità e dimensioni. È possibile utilizzare i seguenti anelli di esempio. Eventuali nuovi anelli devono essere posizionati sotto l'ultimo 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>

La tua anteprima ora corrisponderà a quanto segue.

Sfera dorata con più anelli
(Grande anteprima)

Verifica che il tuo codice corrisponda al codice sorgente per il passaggio 5 su Github. Questo conclude l'arredamento per il globo. Una volta terminata la sfera, aggiungeremo successivamente interattività alla sfera. Nel passaggio successivo, aggiungeremo in modo specifico un cursore visibile con un'animazione di clic quando puntato su oggetti selezionabili.

Rendere le sfere interattive

6. Aggiungi un cursore

In questo passaggio, aggiungeremo un cursore bianco che può attivare oggetti cliccabili. Il cursore è raffigurato sotto.

cliccando su globo
(Grande anteprima)

Nel tag a-camera , aggiungi la seguente entità. L'attributo fuse consente a questa entità di attivare eventi di clic. L'attributo raycaster determina la frequenza e la distanza da controllare per gli oggetti cliccabili. L'attributo objects accetta un selettore per determinare quali entità sono selezionabili. In questo caso, tutti gli oggetti della classe clickable sono cliccabili.

 <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>

Quindi, aggiungi l'animazione del cursore e un anello extra per l'estetica. Posiziona quanto segue all'interno dell'oggetto cursore di entità sopra. Questo aggiunge animazione all'oggetto cursore in modo che i clic siano visibili.

 <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>

Quindi, aggiungi la classe clickable a #orb0 in modo che corrisponda a quanto segue.

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

Verifica che il tuo codice corrisponda al codice sorgente per il passaggio 6 su Github. Nella tua anteprima, trascina il cursore fuori da essi sulla sfera per vedere l'animazione del clic in azione. Questo è raffigurato sotto.

cliccando su globo
(Grande anteprima)

Nota che l'attributo selezionabile è stato aggiunto alla sfera stessa e non al contenitore della sfera. Questo per evitare che gli anelli diventino oggetti cliccabili. In questo modo, l'utente deve cliccare sulle sfere che compongono la sfera stessa.

Nel nostro passaggio finale per questa parte, aggiungerai un'animazione per controllare gli stati di accensione e spegnimento per la sfera.

7. Aggiungi gli stati della sfera

In questo passaggio, animerai la sfera dentro e fuori da uno stato spento al clic. Questo è raffigurato sotto.

Sfera interattiva che risponde ai clic
(Grande anteprima)

Per iniziare, rimpicciolirai e abbasserai la sfera a terra. Aggiungi tag di a-animation a #container-orb0 subito dopo #orb0 . Entrambe le animazioni vengono attivate con un clic e condividono la stessa funzione di allentamento ease-elastic per un leggero rimbalzo.

 <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>

Per enfatizzare ulteriormente lo stato spento, rimuoveremo la luce del punto dorato quando il globo è spento. Tuttavia, le luci della sfera sono posizionate all'esterno dell'oggetto sfera. Pertanto, l'evento click non viene passato alle luci quando si fa clic sulla sfera. Per aggirare questo problema, utilizzeremo alcuni Javascript light per passare l'evento click alla luce. Inserisci il seguente tag di animazione in #light-orb0 . La luce viene attivata da un evento di switch personalizzato.

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

Quindi, aggiungi il seguente listener di eventi clic a #container-orb0 . Questo ritrasmetterà i clic alle luci del globo.

 <a-entity ...>

Verifica che il tuo codice corrisponda al codice sorgente per il passaggio 7 su Github. Infine, apri l'anteprima e sposta il cursore sopra e fuori dal globo per alternare tra gli stati off e on. Questo è raffigurato sotto.

Sfera interattiva che risponde ai clic
(Grande anteprima)

Questo conclude l'interattività della sfera. Il giocatore ora può attivare e disattivare le sfere a piacimento, con stati di attivazione e disattivazione autoesplicativi.

Conclusione

In questo tutorial, hai creato una semplice sfera con stati di attivazione e disattivazione, che possono essere attivati ​​​​disattivando un clic del cursore compatibile con le cuffie VR. Con una serie di diverse tecniche di illuminazione e animazioni, sei stato in grado di distinguere tra i due stati. Questo conclude gli elementi di design della realtà virtuale per le sfere. Nella parte successiva del tutorial, popoleremo le sfere in modo dinamico, aggiungeremo meccaniche di gioco e imposteremo un protocollo di comunicazione tra una coppia di giocatori.