Comment créer un jeu de réalité virtuelle multijoueur en temps réel (Partie 1)
Publié: 2022-03-10Dans 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 :
- Configuration de la scène (étapes 1 à 2)
- Création des orbes (étapes 3 à 5)
- Rendre les orbes interactifs (étapes 6 à 7)
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.
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 :
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 :
- Cliquez sur "Nouveau projet" en haut à droite,
- Cliquez sur "hello-webpage" dans le menu déroulant,
- 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.
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é.
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.
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.
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.
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.
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.
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.
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 :
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.
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.
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.
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.
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.
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.