Artículo de revisión del marco A



A-Frame es un marco basado en la web que le permite crear varias aplicaciones, juegos, escenas en realidad virtual (VR). Todo lo anterior estará disponible directamente desde el navegador de su casco VR. Esta herramienta será útil para aquellos que quieran desarrollar juegos de realidad virtual en un navegador y, por ejemplo, puede ser útil como plataforma para crear aplicaciones web de realidad virtual, sitios y páginas de destino. Los usos de Web BP están limitados solo por su imaginación. De improviso, puedo traer un par de áreas de actividad humana donde BP puede ser útil: educación, medicina, deportes, ventas, ocio.

¿Qué hay adentro?


A-Frame no está escrito desde 0 en WebGL puro, está basado en la biblioteca Three.js . Por lo tanto, le recomiendo que primero comprenda los conceptos básicos de Three.js antes de comenzar a trabajar con A-Frame, aunque esto no es necesario, ya que A-Frame está diseñado para que piense menos en renderizar geometría y centrarse más en la lógica de su aplicación . Es por eso que él, de hecho, y el marco.

Para esto, A-Frame postula tres puntos principales, de los que hablaremos más adelante.

A-Frame funciona con HTML


Muchos elementos básicos de A-Frame, como escena, cámara, caja, esfera, etc., se agregan a la escena a través de etiquetas del mismo nombre con el prefijo a- . Cada artículo similar se registra como personalizado. A-Frame (0.8.0) actualmente usa la especificación 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> 

Este pequeño fragmento de código dibujará una escena WebGL a la que se agregarán dos objetos: un cubo y una esfera con los parámetros dados. Además de los dos elementos mencionados anteriormente, hay una serie de otras primitivas que se pueden agregar a la escena de la misma manera: <a-circle>, <a-cone>, <a-cylinder>, <a-dodecahedron>, <a-icosahedron> , <a-octahedron>, <a-plane>, <a-ring>, <a-tetrahedron>, <a-torus-knot>, <a-torus>, <a-triangle> . También en A-Frame hay una serie de otros elementos que realizan ciertas funciones:

  • <a-cámara> : crea una cámara. Actualmente solo se admite la cámara de perspectiva (PerspectiveCamera).
  • <a-obj-model>, <a-collada-model>, <a-gltf-model> : todos cargan y muestran modelos del formato correspondiente.
  • <a-cursor> : un elemento que le permite realizar diversas acciones: clic, orientación, etc. El cursor está vinculado al centro de la cámara, por lo que siempre estará en el centro de lo que ve el usuario.
  • <a-imagen> : muestra la imagen seleccionada en un plano (<a-plane>).
  • <a-link> es lo mismo que una etiqueta, solo para una escena 3D.
  • <a-sky> : un cilindro enorme alrededor del escenario que te permite mostrar 360 fotos. O simplemente puede llenarlo con un poco de color.
  • <a-sound> : crea una fuente de sonido en una posición determinada.
  • <a-text> : dibuja texto plano.
  • <a-video> - reproduce video en un avión.

También me gustaría señalar que trabajamos con elementos DOM y, por lo tanto, podemos usar la API DOM estándar, que incluye querySelector, getElementById, appendChild, etc.

A-Frame utiliza ECS



ECS (Entity Component System) : patrón de diseño de aplicaciones y juegos. Se generalizó solo en el segundo segmento. Como su nombre lo indica, los tres conceptos básicos de un patrón son Entidad, Componente, Sistema. En la forma clásica, están interconectados de la siguiente manera: tenemos algún objeto contenedor (Entidad) al que podemos agregar componentes. Típicamente, un componente es responsable de una parte separada de la lógica. Por ejemplo, tenemos un objeto Player, tiene un componente Health. Este componente contendrá toda la lógica asociada con la reposición o pérdida de salud del jugador (objeto). Y los sistemas, a su vez, son necesarios para administrar un conjunto de entidades combinadas por algunos componentes. Normalmente, un componente puede registrar una entidad dentro del sistema del mismo nombre.

En A-Frame, este patrón se implementa de manera muy simple y elegante, con la ayuda de atributos. Cualquier elemento de A-Frame - <a-scene>, <a-box>, <a-sphere>, etc. se utilizan como entidades, pero, por supuesto, el elemento <a-entity> se distingue. Su nombre habla por si mismo. Todos los demás elementos son esencialmente envoltorios para componentes y están hechos para su conveniencia, ya que cualquier elemento también se puede crear usando <entidad- . Por ejemplo <a-box> :

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

geometría : en este caso, es el componente que se agregó a la entidad <entidad> . <a-entidad> en sí mismo no tiene ninguna lógica (en el sentido global), y el componente de geometría esencialmente lo convierte en un cubo u otra cosa. Otro componente no menos importante que la geometría es el material . Agrega material a la geometría. El material es responsable de si nuestro cubo brillará como el metal, si tendrá texturas, etc. En Three.js puro , tendríamos que crear geometría separada, material separado, y luego todo esto tendría que combinarse en el caché. En general, este enfoque ahorra tiempo.

Cualquier componente en A-Frame debe registrarse globalmente a través de un diseño especial:

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

Entonces este componente se puede agregar a la escena, o cualquier otro elemento.

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

Como agregamos la devolución de llamada de inicio para nuestro componente, tan pronto como el elemento se agregue al DOM, esta devolución de llamada funcionará y veremos nuestro mensaje en la consola. Hay otras devoluciones de llamada del ciclo de vida en los componentes A-Frame. Hablemos de ellos con más detalle:

  • actualización : se llama tanto durante la inicialización como init, y al actualizar cualquier propiedad de este componente.
  • remove : se llama después de eliminar un componente o entidad que lo contiene. Es decir, si elimina <a-entidad> del DOM, todos sus componentes llamarán a la devolución de llamada de eliminación.
  • tick : se llama cada vez antes de representar la escena. Dentro del bucle de renderizado utiliza requestAnimaitonFrame
  • tock : se llama cada vez que se muestra una escena.
  • reproducir : cada una se llama cuando se reanuda la representación de la escena. Esencialmente después de scene.play ();
  • pausa : se llama cada vez que se detiene la representación de una escena. Esencialmente después de scene.pause ();
  • updateSchema : se llama cada vez después de actualizar el esquema.

Otro concepto de componente importante en A-Frame es la circuitería. El diagrama describe las propiedades del componente. Se define de la siguiente manera:

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

En este caso, nuestro componente my contendrá dos propiedades, arrayProperty e integerProperty . Para pasarlos al componente, debe establecer el valor del atributo correspondiente.

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

Puede obtener estas propiedades dentro del componente a través de la propiedad de datos .

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

Para obtener las propiedades de un componente de la entidad a la que se agrega, puede usar la función getAttribute ligeramente modificada. Al acceder a la entidad A-Frame, devolverá no solo el valor de cadena del atributo, sino el objeto de datos mencionado anteriormente.

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

Aproximadamente de la misma manera, puede cambiar las propiedades de un componente:

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

Ahora hablemos de sistemas. Los sistemas en A-Frame se registran de la misma manera que los componentes:

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

Además del componente, el sistema tiene un circuito y devoluciones de llamada. Solo el sistema tiene solo 5 de ellos: init, play, pause, tick, tock . No es necesario agregar el sistema como componente a la entidad. Se agregará automáticamente a la escena.

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

Si el componente tiene el mismo nombre que el sistema, el sistema estará disponible en this.system .

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

Por lo general, se necesitan sistemas para ensamblar y administrar entidades con componentes relacionados. Aquí, en teoría, debería haber una lógica que se relacione con una colección de entidades. Por ejemplo, controla la apariencia de los enemigos en el juego.

La comunicación en A-Frame ocurre a través de los eventos del navegador


De hecho, por qué reinventar la rueda, si en este momento hay una gran implementación incorporada de editor-suscriptor para elementos DOM. Los eventos DOM le permiten escuchar los eventos del navegador, como una pulsación de tecla, un clic del mouse y otros eventos del usuario. A-Frame nos ofrece una manera conveniente y fácil de comunicarnos entre entidades, componentes y sistemas, a través de eventos del usuario. Para esto, cada elemento A-Frame es parcheado por la función de emisión , toma tres parámetros: el primero es el nombre del evento, el segundo son los datos que se transmitirán, el tercero es si el evento debería aparecer.

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

Puede suscribirse a este evento de la manera habitual para todos nosotros, usando addEventListener:

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

El burbujeo de eventos aquí es un punto muy importante, porque a veces dos entidades que deben comunicarse entre sí están en el mismo nivel, en cuyo caso puede agregar un oyente de eventos al elemento de escena. Como puede ver anteriormente, está disponible dentro de cada elemento a través del enlace sceneEl .

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

En conclusión


Eso, tal vez, es todo lo que quería hablar en este artículo. A-Frame tiene muchos temas diferentes que podrían tratarse, pero este artículo es una revisión y quería enfocar al lector solo en los puntos principales. En el próximo artículo, intentaremos crear una escena básica para probar todo el conocimiento adquirido en la práctica. Gracias a todos!

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


All Articles