Comment créer un jeu de réalité virtuelle multijoueur en temps réel (Partie 1)

Publié: 2022-03-10
Résumé rapide ↬ La réalité virtuelle est un nouveau support immersif pour explorer le contenu, que ce contenu soit un film ( Life of Pi ), ​​un jeu ( Beat Saber ) ou une expérience sociale (comme décrit dans Ready Player One ). Malgré sa nouveauté, la réalité virtuelle ne nécessite pas un ensemble d'outils radicalement différent pour la conception - les mêmes outils que nous utilisons pour le développement de jeux Web, la modélisation 3D et d'autres sont toujours applicables. Ce didacticiel tire parti de votre connaissance du développement Web pour vous lancer dans le développement VR.

Dans cette série de didacticiels, nous allons créer un jeu de réalité virtuelle multijoueur basé sur le Web dans lequel les joueurs devront collaborer pour résoudre un casse-tête. Nous utiliserons A-Frame pour la modélisation VR, MirrorVR pour la synchronisation en temps réel entre appareils et A-Frame Low Poly pour une esthétique low-poly. À la fin de ce didacticiel, vous disposerez d'une démo en ligne entièrement fonctionnelle à laquelle tout le monde pourra jouer.

Chaque paire de joueurs reçoit un anneau d'orbes. Le but est d'« allumer » tous les orbes, où un orbe est « allumé » s'il est élevé et lumineux. Un orbe est « éteint » s'il est plus bas et faible. Cependant, certains orbes "dominants" affectent leurs voisins : s'il change d'état, ses voisins changent également d'état. Seul le joueur 2 peut contrôler les orbes dominants tandis que seul le joueur 1 peut contrôler les orbes non dominants. Cela oblige les deux joueurs à collaborer pour résoudre le puzzle. Dans cette première partie du tutoriel, nous allons construire l'environnement et ajouter les éléments de design pour notre jeu VR.

Les sept étapes de ce didacticiel sont regroupées en trois sections :

  1. Configuration de la scène (étapes 1 à 2)
  2. Création des orbes (étapes 3 à 5)
  3. Rendre les orbes interactifs (étapes 6 à 7)
Plus après saut! Continuez à lire ci-dessous ↓

Cette première partie se terminera par un orbe cliquable qui s'allume et s'éteint (comme illustré ci-dessous). Vous utiliserez A-Frame VR et plusieurs extensions A-Frame.

( Grand aperçu )

Mise en place de la scène

1. Allons-y avec une scène de base

Pour commencer, regardons comment nous pouvons mettre en place une scène simple avec un sol :

Créer une scène simple
Créer une scène simple ( Grand aperçu )

Les trois premières instructions ci-dessous sont extraites de mon article précédent. Vous commencerez par configurer un site Web avec une seule page HTML statique. Cela vous permet de coder à partir de votre bureau et de déployer automatiquement sur le Web. Le site Web déployé peut ensuite être chargé sur votre téléphone mobile et placé dans un casque VR. Alternativement, le site Web déployé peut être chargé par un casque VR autonome.

Commencez par naviguer sur glitch.com. Ensuite, procédez comme suit :

  1. Cliquez sur "Nouveau projet" en haut à droite,
  2. Cliquez sur "hello-webpage" dans le menu déroulant,
  3. Ensuite, cliquez sur index.html dans la barre latérale gauche. Nous l'appellerons votre "éditeur".

Vous devriez maintenant voir l'écran Glitch suivant avec un fichier HTML par défaut.

Projet Glitch : le fichier index.html
Projet Glitch : le fichier index.html ( Grand aperçu )

Comme pour le didacticiel lié ci-dessus, commencez par supprimer tout le code existant dans le fichier index.html actuel. Ensuite, tapez ce qui suit pour un projet webVR de base, en utilisant A-Frame VR. Cela crée une scène vide en utilisant l'éclairage et la caméra par défaut de 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>

Soulevez la caméra à hauteur debout. Selon les recommandations A-Frame VR (problème Github), enveloppez la caméra avec une nouvelle entité et déplacez directement l'entité parente au lieu de la caméra. Entre vos balises a-scene aux lignes 8 et 9, ajoutez ce qui suit.

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

Ensuite, ajoutez une grande boîte pour indiquer le sol, en utilisant a-box . Placez-le directement sous votre appareil photo à partir de l'instruction précédente.

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

Votre fichier index.html doit maintenant correspondre exactement à ce qui suit. Vous pouvez trouver le code source complet ici, sur 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>

Ceci conclut la configuration. Ensuite, nous personnaliserons l'éclairage pour une atmosphère plus mystérieuse.

2. Ajouter une atmosphère

Dans cette étape, nous allons mettre en place le brouillard et l'éclairage personnalisé.

Un aperçu d'une scène simple avec une ambiance sombre
Un aperçu d'une scène simple avec une ambiance sombre ( Grand aperçu )

Ajoutez un brouillard, qui obscurcira les objets éloignés pour nous. Modifiez la balise a-scene à la ligne 8. Ici, nous allons ajouter un brouillard sombre qui obscurcit rapidement les bords du sol, donnant l'effet d'un horizon lointain.

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

Le gris foncé #111 s'estompe linéairement d'une distance de 10 à une distance de 15. Tous les objets à plus de 15 unités sont complètement obscurcis et tous les objets à moins de 10 unités sont complètement visibles. Tout objet entre les deux est partiellement obscurci.

Ajoutez une lumière ambiante pour éclairer les objets du jeu et une lumière unidirectionnelle pour accentuer les surfaces réfléchissantes que vous ajouterez plus tard. Placez-le directement après la balise a-scene que vous avez modifiée dans l'instruction précédente.

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

Directement sous les lumières de l'instruction précédente, ajoutez un ciel sombre. Remarquez que le gris foncé #111 correspond à celui du brouillard lointain.

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

Ceci conclut les modifications de base de l'ambiance et plus largement, la configuration de la scène. Vérifiez que votre code correspond exactement au code source de l'étape 2 sur Github. Ensuite, nous ajouterons un orbe low-poly et commencerons à personnaliser l'esthétique de l'orbe.

Création des orbes

3. Créer un orbe low-poly

Dans cette étape, nous allons créer un orbe rotatif et réfléchissant comme illustré ci-dessous. L'orbe est composé de deux sphères low-poly stylisées avec quelques astuces pour suggérer un matériau réfléchissant.

Orbe rotatif et réfléchissant
( Grand aperçu )

Commencez par importer la bibliothèque low-poly dans votre balise head . Insérez ce qui suit entre les lignes 4 et 5.

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

Créez un carrousel, un wrapper et un conteneur orb. Le carousel contiendra plusieurs orbes, l' wrapper nous permettra de faire pivoter tous les orbes autour d'un axe central sans faire tourner chaque orbe individuellement, et le container - comme son nom l'indique - contiendra tous les composants de l'orbe.

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

À l'intérieur du conteneur d'orbe, ajoutez l'orbe lui-même : une sphère est légèrement translucide et décalée, et l'autre est complètement solide. Les deux surfaces réfléchissantes combinées imitent.

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

Enfin, faites pivoter la sphère indéfiniment en ajoutant la balise a-animation suivante immédiatement après la lp-sphere à l'intérieur de l'entité .orb dans la dernière instruction.

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

Votre code source pour les wrappers d'orbe et l'orbe lui-même doivent correspondre exactement à ce qui suit.

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

Vérifiez que votre code source correspond au code source complet de l'étape 3 sur Github. Votre aperçu doit maintenant correspondre à ce qui suit.

Orbe rotatif et réfléchissant
( Grand aperçu )

Ensuite, nous ajouterons plus d'éclairage à l'orbe pour une teinte dorée.

4. Allumez l'orbe

Dans cette étape, nous ajouterons deux lumières, une colorée et une blanche. Cela produit l'effet suivant.

Orbe éclairé par des lumières ponctuelles
( Grand aperçu )

Commencez par ajouter la lumière blanche pour éclairer l'objet par le dessous. Nous utiliserons une lumière ponctuelle. Juste avant #orb0 mais dans #container-orb0 , ajoutez le point lumineux décalé suivant.

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

Dans votre aperçu, vous verrez ce qui suit.

Orbe éclairé avec un point lumineux blanc
( Grand aperçu )

Par défaut, les lumières ne diminuent pas avec la distance. En ajoutant distance="8" , nous nous assurons que la lumière se désintègre complètement avec une distance de 8 unités, pour empêcher la lumière ponctuelle d'éclairer toute la scène. Ensuite, ajoutez la lumière dorée. Ajoutez ce qui suit directement au-dessus de la dernière lumière.

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

Vérifiez que votre code correspond exactement au code source de l'étape 4. Votre aperçu correspondra désormais à ce qui suit.

Orbe éclairé par des lumières ponctuelles
( Grand aperçu )

Ensuite, vous apporterez votre dernière modification esthétique à l'orbe et ajouterez des anneaux rotatifs.

5. Ajouter des anneaux

Dans cette étape, vous produirez l'orbe final, comme illustré ci-dessous.

Orbe doré avec plusieurs anneaux
( Grand aperçu )

Ajoutez un anneau dans #container-orb0 directement avant #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>

Notez que l'anneau lui-même ne contient pas de couleur, car la couleur sera imprégnée par la lumière ponctuelle à l'étape précédente. De plus, le material="side:double" est important car, sans lui, l'arrière de l'anneau ne serait pas rendu ; cela signifie que l'anneau disparaîtrait pendant la moitié de sa rotation.

Cependant, l'aperçu avec uniquement le code ci-dessus ne sera pas différent. En effet, l'anneau est actuellement perpendiculaire à l'écran. Ainsi, seul le "côté" de l'anneau (qui a une épaisseur de 0) est visible. Placez l'animation suivante entre les balises a-ring dans l'instruction précédente.

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

Votre aperçu doit maintenant correspondre aux éléments suivants :

Orbe doré avec anneau
( Grand aperçu )

Créez un nombre variable d'anneaux avec différents axes de rotation, vitesses et tailles. Vous pouvez utiliser les exemples de sonneries suivants. Tout nouvel anneau doit être placé sous le dernier a-ring A .

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

Votre aperçu correspondra désormais à ce qui suit.

Orbe doré avec plusieurs anneaux
( Grand aperçu )

Vérifiez que votre code correspond au code source de l'étape 5 sur Github. Ceci conclut le décor de l'orbe. Une fois l'orbe terminé, nous ajouterons ensuite de l'interactivité à l'orbe. Dans l'étape suivante, nous ajouterons spécifiquement un curseur visible avec une animation de clic lorsqu'il est pointé sur des objets cliquables.

Rendre les orbes interactifs

6. Ajouter un curseur

Dans cette étape, nous allons ajouter un curseur blanc qui peut déclencher des objets cliquables. Le curseur est illustré ci-dessous.

en cliquant sur l'orbe
( Grand aperçu )

Dans votre balise a-camera , ajoutez l'entité suivante. L'attribut fuse permet à cette entité de déclencher des événements de clic. L'attribut raycaster détermine la fréquence et la distance de vérification des objets cliquables. L'attribut objects accepte un sélecteur pour déterminer quelles entités sont cliquables. Dans ce cas, tous les objets de la classe clickable sont cliquables.

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

Ensuite, ajoutez une animation de curseur et un anneau supplémentaire pour l'esthétique. Placez ce qui suit à l'intérieur de l'objet curseur d'entité ci-dessus. Cela ajoute une animation à l'objet curseur afin que les clics soient visibles.

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

Ensuite, ajoutez la classe clickable au #orb0 pour correspondre à ce qui suit.

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

Vérifiez que votre code correspond au code source de l'étape 6 sur Github. Dans votre aperçu, faites glisser votre curseur hors d'eux sur l'orbe pour voir l'animation de clic en action. Ceci est illustré ci-dessous.

en cliquant sur l'orbe
( Grand aperçu )

Notez que l'attribut cliquable a été ajouté à l'orbe lui-même et non au conteneur d'orbe. Ceci afin d'éviter que les anneaux ne deviennent des objets cliquables. De cette façon, l'utilisateur doit cliquer sur les sphères qui composent l'orbe lui-même.

Dans notre dernière étape pour cette partie, vous ajouterez une animation pour contrôler les états d'activation et de désactivation de l'orbe.

7. Ajouter des états Orb

Dans cette étape, vous animerez l'orbe dans et hors d'un état désactivé au clic. Ceci est illustré ci-dessous.

Orbe interactif répondant aux clics
( Grand aperçu )

Pour commencer, vous allez rétrécir et abaisser l'orbe au sol. Ajoutez des balises a-animation au #container-orb0 juste après #orb0 . Les deux animations sont déclenchées par un clic et partagent la même fonction d'easing ease-elastic pour un léger rebond.

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

Pour accentuer davantage l'état éteint, nous supprimerons la lumière du point doré lorsque l'orbe est éteint. Cependant, les lumières de l'orbe sont placées à l'extérieur de l'objet orbe. Ainsi, l'événement de clic n'est pas transmis aux lumières lorsque l'orbe est cliqué. Pour contourner ce problème, nous allons utiliser du Javascript léger pour transmettre l'événement click à la lumière. Placez la balise d'animation suivante dans #light-orb0 . La lumière est déclenchée par un événement de switch personnalisé.

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

Ensuite, ajoutez l'écouteur d'événement click suivant au #container-orb0 . Cela transmettra les clics aux lumières orb.

 <a-entity ...>

Vérifiez que votre code correspond au code source de l'étape 7 sur Github. Enfin, affichez votre aperçu et déplacez le curseur sur et hors de l'orbe pour basculer entre les états désactivé et activé. Ceci est illustré ci-dessous.

Orbe interactif répondant aux clics
( Grand aperçu )

Ceci conclut l'interactivité de l'orbe. Le joueur peut désormais activer et désactiver les orbes à volonté, avec des états d'activation et de désactivation explicites.

Conclusion

Dans ce didacticiel, vous avez construit un orbe simple avec des états activés et désactivés, qui peuvent être activés par un clic de curseur adapté aux casques VR. Avec un certain nombre de techniques d'éclairage et d'animations différentes, vous avez pu faire la distinction entre les deux états. Ceci conclut les éléments de conception de réalité virtuelle pour les orbes. Dans la prochaine partie du didacticiel, nous allons peupler dynamiquement les orbes, ajouter des mécanismes de jeu et mettre en place un protocole de communication entre deux joueurs.