Article sur la révision du cadre A



A-Frame est un framework basé sur le Web qui vous permet de créer diverses applications, jeux, scènes en réalité virtuelle (VR). Tout ce qui précède sera disponible directement depuis le navigateur de votre casque VR. Cet outil sera utile pour ceux qui souhaitent développer des jeux VR dans un navigateur, et par exemple, il peut être utile comme plate-forme pour créer des applications, des sites, des pages de destination Web VR. Les utilisations de Web BP ne sont limitées que par votre imagination. Offhand je peux apporter quelques domaines de l'activité humaine où la PA peut être utile: l'éducation, la médecine, les sports, les ventes, les loisirs.

Qu'y a-t-il à l'intérieur?


A-Frame n'est pas écrit à partir de 0 sur WebGL pur, il est basé sur la bibliothèque Three.js . Par conséquent, je vous recommande de comprendre d'abord les concepts de base de Three.js avant de commencer à travailler avec A-Frame, bien que cela ne soit pas nécessaire, car A-Frame est conçu de sorte que vous pensiez le moins au rendu de la géométrie et que vous vous concentriez davantage sur la logique de votre application. . Voilà pourquoi lui, en fait, et le cadre.

Pour cela, A-Frame postule trois points principaux, dont nous parlerons plus loin.

A-Frame fonctionne avec HTML


De nombreux éléments de base du cadre A, tels que scène, appareil photo, boîte, sphère, etc., sont ajoutés à la scène via des balises du même nom avec le préfixe a- . Chaque article similaire est enregistré comme personnalisé. A-Frame (0.8.0) utilise actuellement la spécification v0.

<a-scene> <a-box position="-1 0.5 -3" rotation="0 45 0" color="#4CC3D9"></a-box> <a-sphere position="0 1.25 -5" radius="1.25" color="#EF2D5E"></a-sphere> </a-scene> 

Ce petit fragment de code dessinera une scène WebGL à laquelle deux objets seront ajoutés: un cube et une sphère avec les paramètres donnés. En plus des deux éléments mentionnés ci-dessus, il existe un certain nombre d'autres primitives qui peuvent être ajoutées à la scène de la même manière: <a-circle>, <a-cone>, <a-cylinder>, <a-dodecahedron>, <a-icosahedron> , <a-octaèdre>, <a-plane>, <a-ring>, <a-tetrahedron>, <a-torus-knot>, <a-torus>, <a-triangle> . Dans A-Frame, il existe également un certain nombre d'autres éléments qui remplissent certaines fonctions:

  • <a-camera> - crée une caméra. Seule la caméra en perspective (PerspectiveCamera) est actuellement prise en charge.
  • <a-obj-model>, <a-collada-model>, <a-gltf-model> - ils chargent et affichent tous des modèles du format correspondant.
  • <a-cursor> - un élément qui vous permet d'effectuer diverses actions: clic, guidage, etc. Le curseur est lié au centre de la caméra, il sera donc toujours au centre de ce que voit l'utilisateur.
  • <a-image> - affiche l'image sélectionnée sur un plan (<a-plane>).
  • <a-link> est identique à une balise, uniquement pour une scène 3D.
  • <a-sky> - un énorme cylindre autour de la scène qui vous permet d'afficher 360 photos. Ou vous pouvez simplement le remplir de couleur.
  • <a-sound> - crée une source sonore dans une position donnée.
  • <a-text> - dessine un texte plat.
  • <a-video> - lit la vidéo dans un avion.

Je voudrais également noter que nous travaillons avec des éléments DOM et que nous pouvons donc utiliser l'API DOM standard, notamment querySelector, getElementById, appendChild, etc.

A-Frame utilise ECS



ECS (Entity Component System) - modèle de conception d'application et de jeu. Il était répandu uniquement dans le deuxième segment. Comme son nom l'indique, les trois concepts de base d'un modèle sont Entité, Composant, Système. Dans la forme classique, ils sont interconnectés comme suit: nous avons un objet conteneur (Entity) auquel nous pouvons ajouter des composants. En règle générale, un composant est responsable d'une partie distincte de la logique. Par exemple, nous avons un objet Player, il a un composant Health. Ce composant contiendra toute la logique associée à la reconstitution ou à la perte de santé du joueur (objet). Et les systèmes, à leur tour, sont nécessaires pour gérer un ensemble d'entités combinées par certains composants. En règle générale, un composant peut enregistrer une entité dans le système du même nom.

Dans A-Frame, ce modèle est mis en œuvre de manière très simple et élégante - à l'aide d'attributs. Tous les éléments A-Frame - <a-scene>, <a-box>, <a-sphere>, etc. sont utilisés comme entités. Mais, bien sûr, l'élément <a-entity> se distingue. Son nom parle de lui-même. Tous les autres éléments sont essentiellement des wrappers pour les composants et sont conçus pour plus de commodité, car tout élément peut également être créé à l'aide de <a-entity> . Par exemple <a-box> :

 <a-entity geometry="primitive: box; width: 1; height: 1; depth: 1"></a-entity> 

géométrie - dans ce cas, est le composant qui a été ajouté à l' entité <a-entity> . <a-entity> lui - même n'a pas de logique (au sens global), et le composant géométrique le transforme essentiellement en cube ou autre chose. Un autre composant non moins important que la géométrie est le matériau . Il ajoute du matériau à la géométrie. Le matériau est responsable de savoir si notre cube brillera comme du métal, s'il aura des textures, etc. Dans Three.js pur , nous devions créer une géométrie séparée, un matériau séparé, puis tout cela devrait être combiné dans le cache. En général, cette approche fait gagner du temps.

Tout composant dans A-Frame doit être enregistré globalement via une conception spéciale:

 AFRAME.registerComponent('hello-world', { init: function () { console.log('Hello, World!'); } }); 

Ensuite, ce composant peut être ajouté à la scène ou à tout autre élément.

 <a-entity hello-world></a-entity> 

Depuis que nous avons ajouté le rappel init pour notre composant, dès que l'élément est ajouté au DOM, ce rappel fonctionnera et nous verrons notre message dans la console. Il existe d'autres rappels de cycle de vie dans les composants A-Frame. Arrêtons-nous plus en détail sur eux:

  • update - est appelé à la fois lors de l'initialisation en tant qu'init et lors de la mise à jour d'une propriété de ce composant.
  • remove - appelé après la suppression d'un composant ou d'une entité le contenant. Autrement dit, si vous supprimez <a-entity> du DOM, tous ses composants appellent remove callback.
  • tick - appelé à chaque fois avant le rendu de la scène. À l'intérieur de la boucle de rendu utilise requestAnimaitonFrame
  • tock - appelé à chaque fois après le rendu d'une scène.
  • play - chacun est appelé lorsque la scène reprend le rendu. Essentiellement après scene.play ();
  • pause - Appelé chaque fois qu'une scène arrête le rendu. Essentiellement après scene.pause ();
  • updateSchema - appelé à chaque fois après la mise à jour du schéma.

Un autre concept de composant important dans A-Frame est le circuit. Le diagramme décrit les propriétés du composant. Il est défini comme suit:

 AFRAME.registerComponent('my-component', { schema: { arrayProperty: {type: 'array', default: []}, integerProperty: {type: 'int', default: 5} } } 

Dans ce cas, notre composant my contiendra deux propriétés, arrayProperty et integerProperty . Pour les transmettre au composant, vous devez définir la valeur de l'attribut correspondant.

 <a-entity my-component="arrayProperty: 1,2,3; integerProperty: 7"></a-entity> 

Vous pouvez obtenir ces propriétés à l'intérieur du composant via la propriété data .

 AFRAME.registerComponent('my-component', { schema: { arrayProperty: {type: 'array', default: []}, integerProperty: {type: 'int', default: 5} }, init: function () { console.log(this.data); } } 

Pour obtenir les propriétés d'un composant à partir de l'entité à laquelle il est ajouté, vous pouvez utiliser la fonction getAttribute légèrement modifiée. Lors de l'accès à l'entité A-Frame, il renverra non seulement la valeur de chaîne de l'attribut, mais l'objet de données mentionné ci-dessus.

  console.log(this.el.getAttribute('my-component')); // {arrayProperty: [1,2,3], integerProperty: 7} 

De la même manière, vous pouvez modifier les propriétés d'un composant:

 this.el.setAttribute('my-component',{arrayProperty: [], integerProperty: 5}) 

Parlons maintenant des systèmes. Les systèmes en A-Frame sont enregistrés de la même manière que les composants:

 AFRAME.registerSystem('my-system', { schema: {}, init: function () { console.log('Hello, System!'); }, }); 

En plus du composant, le système possède un circuit et des rappels. Seul le système n'en a que 5: init, play, pause, tick, tock . Il n'est pas nécessaire d'ajouter le système en tant que composant à l'entité. Il sera automatiquement ajouté à la scène.

 this.el.sceneEl.systems['my-system']; 

Si le composant porte le même nom que le système, le système sera disponible sur this.system .

 AFRAME.registerSystem('enemy', { schema: {}, init: function () {}, }); AFRAME.registerComponent('enemy', { schema: {}, init: function () { const enemySystem = this.system; }, }); 

En règle générale, les systèmes sont nécessaires pour assembler et gérer des entités avec des composants connexes. Ici, en théorie, il devrait y avoir une logique qui se rapporte à une collection d'entités. Par exemple, contrôlez l'apparence des ennemis dans le jeu.

La communication dans A-Frame se fait par le biais des événements du navigateur


En effet, pourquoi réinventer la roue, s'il existe actuellement une excellente implémentation éditeur-abonné intégrée pour les éléments DOM. Les événements DOM vous permettent d'écouter les deux événements du navigateur, tels qu'une frappe de touche, un clic de souris et d'autres événements utilisateur. A-Frame nous offre un moyen pratique et facile de communiquer entre les entités, les composants et les systèmes, via des événements utilisateur. Pour cela, chaque élément A-Frame est patché par la fonction emit , il prend trois paramètres: le premier est le nom de l'événement, le second est les données à transmettre, le troisième est de savoir si l'événement doit apparaître.

 this.el.emit('start-game', {level: 1}, false); 

Vous pouvez vous abonner à cet événement de la manière habituelle pour nous tous, en utilisant addEventListener:

 const someEntity = document.getElementById('someEntity'); someEntity.addEventListener('start-game', () => {...}); 

Le bouillonnement des événements ici est un point très important, car parfois deux entités qui doivent communiquer entre elles sont au même niveau, auquel cas vous pouvez ajouter un écouteur d'événements à l'élément de scène. Comme vous pouvez le voir précédemment, il est disponible à l'intérieur de chaque élément via le lien sceneEl .

 this.el.sceneEl.addEventListener('start-game', () => {...}); 

En conclusion


C'est peut-être tout ce dont je voulais parler dans cet article. A-Frame a beaucoup de sujets différents qui pourraient être couverts, mais cet article est une revue et je voulais concentrer le lecteur uniquement sur les points principaux. Dans le prochain article, nous allons essayer de créer une scène de base afin de tester toutes les connaissances acquises dans la pratique. Merci à tous!

Source: https://habr.com/ru/post/fr439416/


All Articles