La adición de los enemigos para una HTML5 Mario-estilo de Plataformas – GameDev Academia

NOTA:. Este tutorial no se actualiza a la versión más reciente Quinto y no correr con ella

HTML5 Mario-estilo de plataformas Series con Quinto:

¿Es un hablante de francés? Si es así, gracias a Alejandro Bianchi se puede disfrutar de una adaptada versión francesa de este tutorial.

Este tutorial es la segunda parte de la serie de plataformas Quinto. En el primer tutorial que hemos aprendido algunos conceptos básicos del marco, construyen un nivel básico usando el editor de mapas de baldosa, cargamos el nivel en nuestro juego e implementado una clase de Jugador que podemos controlar mediante el teclado y moverse alrededor del nivel.

En este segundo tutorial vamos a añadir enemigos al nivel. Vamos a implementar dos tipos de enemigos: “los enemigos de tierra” y “enemigos verticales”. También vamos a cubrir cómo podemos tener nuestros enemigos escanear el entorno que les rodea y actuar en consecuencia.

Tabla de contenidos

Tutorial objetivos

  1. La creación de criaturas que siguen las reglas de movimiento y comportamiento simples
  2. Uso de la detección de colisiones para matar al jugador o los enemigos
  3. entender el método de paso de bucle juego ()
  4. Aprende a crear componentes reutilizables
  5. Tener enemigos “observar” en torno a ellos y actuar en consecuencia
  6. elementos nivel de carga de un objeto JSON

    HTML5 dev juego, así!

    Si usted está disfrutando de este tutorial y quiere mucho más de estas cosas no dude en visitar nuestra desarrollo de juegos HTML5 cursos en línea que cubren todos los aspectos básicos para empezar:


    Requisitos

    Como ya se mencionó en la introducción, debe haber completado el tutorial anterior Quinto. Los requisitos para estos serie de tutoriales son:


    • La familiaridad con HTML, CSS, JavaScript y conceptos básicos orientados a objetos.
    • Clonar o descarga Quinto de ella de la página de Github.
    • Configuración de un servidor web local. Tenemos que ejecutar el código en este tutorial en un servidor web y no por simplemente haciendo doble clic en los archivos. WAMP para Windows, MAMP para Mac. En Linux sólo tiene que escribir sudo apt-get install apache2.
    • Descargar e instalar el editor del juego de baldosa, disponible para Linux, Mac y Windows
    • Haga que su IDE favorito listo (Netbeans, Eclipse, Sublime2, Notepad ++, VIM, o cualquier herramienta que se utiliza para la codificación).
    • Haga que sus nudillos agrietados y listo para la codificación.

      Tutorial Activos

      Obtener el código fuente completo tutorial y las imágenes aquí. Todas las imágenes utilizadas en este tutorial tienen una licencia de dominio público.
      El cara a cara!
      He proporcionado los archivos Quintus entre el código fuente tutorial, pero ten en cuenta que el marco es en fuerte desarrollo. Es mejor si usted acaba de agarrar ellos directamente desde la página de Github. Además, mantener un ojo en el repositorio como usted trabaja en sus partidos desde que se añaden nuevas características.

      Killer Moscas

      Comenzaremos creando una nueva clase que hereda de Q.Sprite. VerticalEnemies como yo los he llamado será moscas exóticas que sólo se mueven arriba y abajo. Usted puede caminar sobre ellos para matarlos y si las toca en cualquier otra forma que podrás matar.

      El movimiento vertical estará dentro de un rango. Vamos a llamar a la distancia se moverán de su ubicación inicial “rangey”. Así que si defino rangey = 100 significa que se moverán 100 píxeles hacia arriba desde el principio, luego hacia abajo hasta que van de 100 píxeles de la ubicación inicial.
      // enemigo que sube y downQ.Sprite.extend ( «VerticalEnemy», {init: function (p) {this._super (p, {vy: -100, rangey: 200, gravedad: 0}); this.add ( «2D»); this.p.initialY = this.py; // TODO: cheque por colisiones jugador, troquel o matar consecuencia}, paso: function (dt) {// TODO: movimiento gama actualización dentro del bucle de juego} }); 1234567891011121314 // enemigo que sube y downQ.Sprite.extend ( «VerticalEnemy», {init: function (p) {this._super (p, {vy: -100, rangey: 200, gravedad: 0}) ; this.add ( «2D»); this.p.initialY = this.py; // TODO: cheque por colisiones jugador, die o matar consecuencia}, paso: function (dt) {// TODO: movimiento gama actualización dentro de el bucle de juego}});

      analise Vamos paso a paso. Definimos nuestra clase y le dan un valor predeterminado rangey de 200 píxeles. También hemos establecido la gravedad a 0, lo que significa que no se caigan al suelo, pero flotarán en su lugar (la gravedad viene dada por el componente 2d, que todavía necesitamos para la detección de colisiones más fácil). El parámetro initialy almacenará la ubicación inicial en el eje Y, lo que vamos a utilizar en nuestros cálculos.

      El paso () será ejecutado varias veces por segundo y será utilizado para comprobar las cosas que “deben ser controladas todo el tiempo”. Esto es lo que llamamos el juego Loop, un concepto importante en el desarrollo del juego. El dt parámetro representa la cantidad de tiempo en segundos que ha pasado desde el método de la etapa () se llama pasado.

      Vamos a añadir el código dentro de la etapa () para comprobar que nos estamos moviendo dentro de nuestra gama, y ​​con las instrucciones del interruptor una vez se llega a las fronteras de este rango:
      paso: function (dt) {if (this.py – this.p.initialY & gt; = this.p.rangeY & amp; & amp; this.p.vy & gt; 0) {this.p.vy = -this.p .vy; } Else if (-this.p.y + this.p.initialY & gt; = this.p.rangeY & amp; & amp; this.p.vy & lt; 0) {this.p.vy = -this.p.vy; }} 12345678step: function (dt) {if (this.py-this.p.initialY & gt; = this.p.rangeY & amp; & amp; this.p.vy & gt; 0) {this.p.vy = -this.p. vy;} elseif (-this.p.y + this.p.initialY & gt; = this.p.rangeY & amp; & amp; this.p.vy & lt; 0) {this.p.vy = -this.p.vy;} }

      en Quinto y cuando se utiliza la etiqueta canvas (y en todos los demás marcos de juego que estoy familiarizado con la materia) el eje comienza en cero en la parte superior y es positivo cuando va hacia abajo. El eje X es igual a cero a la izquierda como de costumbre.

      Si llegamos a la parte inferior de la gama mientras se mueve arriba (vy es nuestra velocidad en Y, lo que es positivo cuando va hacia abajo) entonces debemos cambiar de dirección (ajuste vy a -vy). Lo mismo se aplica para cuando se va para arriba.

      Así que esa es la forma en que podemos utilizar el paso () para comprobar si hay cosas en cada iteración del juego. Empezar a pensar en todas las posibilidades que esto abre y lo poderoso que es. En el bucle del juego se puede comprobar y actualizar casi todo. En realidad, así es como funciona el marco detrás de las escenas! si se abre quintus_2d.js encontrará el paso () que se utiliza para la detección de colisiones, movimiento, etc.
      El cara a cara!
      Pase por lo menos media hora mirando el código de la biblioteca Quinto. No se limite a apoderarse de las cosas a partir de los ejemplos que encuentras en la web. Lo necesario para pasar el tiempo mirando cómo las ampollas de la obra marco. Usted se sorprenderá de lo intuitivo y sencillo que es.

      Entonces, ¿qué si toca las moscas? vamos, que depende de donde se tocan (y sí, todavía estamos hablando de desarrollo del juego aquí). Si pisas, los matas (puro estilo Mario). Si usted los golpea a ambos lados o en la parte inferior luego de su muerte. Vamos a añadir el código restante:
      init: function (p) {this._super (p, {vy: -100, rangey: 200, gravedad: 0}); this.add ( «2D»); this.p.initialY = this.p.y; this.on ( «bump.left, bump.right, bump.bottom», la función (colisión) {if (collision.obj.isA ( «Player»)) {Q.stageScene ( «Final de partida», 1, {label: «Juego sobre»}); collision.obj.destroy ();}}); this.on ( «bump.top», la función (colisión) {if (collision.obj.isA ( «Jugador»)) {collision.obj.p.vy = -100; this.destroy ();}}); }, 12345678910111213141516171819init: function (p) {this._super (p, {vy: -100, rangey: 200, gravedad: 0}); this.add ( «2D»); this.p.initialY = this.py; this.on ( «bump.left, bump.right, bump.bottom», la función (colisión) {if (collision.obj.isA ( «Player»)) {Q.stageScene ( «Final de partida», 1, {label: «Juego sobre»}); collision.obj.destroy ();}}); this.on ( «bump.top», la función (colisión) {if (collision.obj.isA ( «jugador»)) {colisión. obj.p.vy = -100; this.destroy ();}});},

      Con this.on estamos escuchando para eventos. Los eventos son unos elementos centrales en el marco Quinto y es así como se puede escuchar por ellos. Encontrará la definición de la protuberancia. * Eventos dentro quintus_2d.js.

      Cuando se activa la colisión, se puede comprobar la clase de elemento que hemos chocado con el uso de collision.obj.isA (…).

      Si el jugador golpea al enemigo en todos los lados, excepto la parte superior un “game over” escena tendrá lugar (todavía tenemos que crearla) y el jugador objeto destruido.

      Si pisamos los enemigos, el jugador recibe un poco hacia atrás de rebote y el enemigo es destruido.

      Juego Escena Durante

      En el siguiente tutorial vamos a implementar vidas jugador. Por ahora el juego va a ser duro, si se muere una vez que el juego ha terminado. Y por simplicidad estamos sólo va a volver a cargar la página en el juego. Agregue el siguiente código escena puesta en escena:
      Q.scene ( «Final de partida», la función (etapa) {alert ( «game over»); window.location = «»;}); 1234Q.scene ( «Final de partida», la función (etapa) {alert ( «game over» ); window.location = «»;});

      Mostrando los enemigos

      Dentro de la level1 inicialización puede crear enemigos de la misma manera que hemos creado el jugador:
      stage.insert (nuevo Q.VerticalEnemy ({x: 800, y: 120, rangey: 70, activo: «fly.png»})); 1stage.insert (newQ.VerticalEnemy ({x: 800, y: 120, rangey: 70, activo:. «fly.png»}));

      Usted debe ser capaz de crear, matar y morir por las moscas ahora


      Juicy limos

      El segundo tipo de enemigo se irán sumando aquí son criaturas que se mueven en el nivel del suelo (I GroundEnemies los llamó). Si llegan a un pasillo o el borde de un acantilado que se conviertan en su espalda y se mueven en la dirección opuesta (volteando el sprite así a la cara lo mismo).
      // enemigo que camina alrededor Q.Sprite.extend ( «GroundEnemy», {init: function (p) {this._super (p, {VX: -100, defaultDirection: «izquierda»}); this.add ( «2d , aiBounce «); this.on (» bump.left, bump.right, bump.bottom», la función (colisión) {if (collision.obj.isA ( «jugador»)) {Q.stageScene ( «Final de partida», 1, {label: «Juego sobre»}); collision.obj.destroy ();}}); this.on ( «bump.top», la función (colisión) {if (collision.obj.isA ( «jugador» )) {// hacer que el jugador salto collision.obj.p.vy = -300; // matanza this.destroy enemigo ();}});}, paso: la función (dt) {// TODO para bordes y vuelta atrás cuando la búsqueda de ellos}}); // 1234567891011121314151617181920212223242526 enemigo que camina alrededor Q.Sprite.extend ( «GroundEnemy», {init: function (p) {this._super (p, {VX: -100, defaultDirection: «izquierda» }); this.add ( «2d, aiBounce»); this.on ( «bump.left, bump.right, bump.bottom», la función (colisión) {if (collision.obj.isA ( «jugador»)) {Q.stageScene ( «Final de partida», 1, {label: «Juego sobre»}); collision.obj.destroy ();}}); this.on ( «bump.top», la función (colisión) {if ( collision.obj.isA ( «Pl ayer «)) {// hacer que el jugador jumpcollision.obj.p.vy = -300; // enemythis.destroy kill ();}});}, paso: function (dt) {// TODO para bordes y a su vez atrás cuando la búsqueda de ellos}});

      lo que hemos añadido anteriormente es más o menos la misma que añadido para el VerticalEnemy, con la única diferencia de que incluimos el componente “aiBounce”, que da a los enemigos un comportamiento básico: caminar y dar la vuelta al chocar con las paredes. Os recomiendo echar un vistazo a este componente en quintus_2d.js, ya que le dará más consejos sobre cómo crear su propia cuenta.

      Ya que estamos duplicando el código que lo mejor es crear un componente reutilizable llamado “commonEnemy” y actualizar el código un poco:
      // componente para enemigo común behaviorsQ.component ( «commonEnemy», {añadido: function () {entidad var = this.entity; entity.on ( «bump.left, bump.right, bump.bottom», la función (colisión) {if (collision.obj.isA ( «jugador»)) {Q.stageScene ( «Final de partida», 1, {label: «Juego sobre»}); collision.obj.destroy ();}}); entity.on ( «bump.top», la función (colisión) {if (collision.obj.isA ( «jugador»)) {// hacer que el jugador salto collision.obj.p.vy = -100; // matanza enemigo this.destroy ();}});},}); // enemigo que camina alrededor Q.Sprite.extend ( «GroundEnemy», {init: function (p) {this._super (p, {VX: -100, defaultDirection: «izquierda»}); this.add ( «2d, aiBounce, commonEnemy»);}, paso: function (dt) {// TODO}}); // enemigo que sube y downQ.Sprite.extend ( «VerticalEnemy «, {init: function (p) {this._super (p, {vy: -100, rangey: 200, gravedad: 0}); this.add ( «2d, commonEnemy»); this.p.initialY = esta .py;}, paso: function (dt) {if (this.py – this.p.initialY & gt; = this.p.rangeY & amp; & amp; this.p.vy & gt; 0) {this.p.vy = -this.p.vy;} els E Si (-this.p.y + this.p.initialY & gt; = this.p.rangeY & amp; & amp; this.p.vy & lt; 0) {this.p.vy = -this.p.vy; }}}); 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950 // componente para enemigo común behaviorsQ.component ( «commonEnemy», {añadido: function () {varentity = this.entity; entity.on ( «bump.left, bump.right, bump.bottom» , la función (colisión) {if (collision.obj.isA ( «jugador»)) {Q.stageScene ( «Final de partida», 1, {label: «Juego sobre»}); collision.obj.destroy ();}} ); entity.on ( «bump.top», la función (colisión) {if (collision.obj.isA ( «jugador»)) {// hacer que el jugador jumpcollision.obj.p.vy = -100; // matanza enemythis.destroy ();}});},}); // enemigo que camina alrededor Q.Sprite.extend ( «GroundEnemy», {init: function (p) {this._super (p, {VX: -100 , defaultDirection: «izquierda»}); this.add ( «2d, aiBounce, commonEnemy»);}, paso: function (dt) {// TODO}}); // enemigo que sube y downQ.Sprite.extend ( «VerticalEnemy», {init: function (p) {this._super (p, {vy: -100, rangey: 200, gravedad: 0}); this.add ( «2d, commonEnemy»); this.p. initialy = this.py;}, paso: function (dt) {if (this.py-this.p.initialY & gt; = this.p.rangeY & amp; & amp; this.p.vy & gt; 0) {this.p.vy = -ésimo is.p.vy;} elseif (-this.p.y + this.p.initialY & gt; = this.p.rangeY & amp; & amp; this.p.vy & lt; 0) {this.p.vy = -this.p .vy;}}});

      se ejecuta la “) añadido (” método dentro de la creación de componentes una vez que el componente se carga al objeto. Vemos cómo el interior de este método se obtiene el enemigo por conseguir this.entity, después de lo cual se puede casi se refieren al enemigo como si estuviera en su propio método init ().

      Escaneado de Medio Ambiente

      Si se han fijado en el código anterior que he dejado el método el paso () de la GroundEnemy. Vamos a utilizar el bucle del juego para comprobar si hay cantos, si nuestros enemigos caerán por el acantilado.
      Esta característica podría convertirse pronto en una parte del componente aiBounce

      Antes de abandonar el código quiero explicar lo que estamos tratando de hacer:.


      • Queremos, en cada paso, para comprobar los azulejos debajo y en frente de nuestro monstruo, y leyó lo que encontremos allí.
      • Si sólo hay otra ficha, seguir caminando.
      • Si no hay azulejos que significa que estamos llegando a la orilla. En este caso la espalda vuelta y caminar en la dirección opuesta
      • Esta es una característica muy rudimentario AI, estamos dando nuestra limo alguna percepción básica del mundo alrededor de ella
      • Quinto lo hace fácil mediante el uso del método de localización (). Especificamos la etapa actual, las coordenadas y el tipo de colisión y nos da todo lo que se encuentra allí

        paso: function (dt) {var DirX = this.p.vx / Math.abs (this.p.vx); suelo var = Q.stage () localizar (this.p.x, this.p.y + this.p.h / 2 + 1, Q.SPRITE_DEFAULT).; var nextTile = Q.stage () localizar (this.p.x + DirX * this.p.w / 2 + DirX, this.p.y + this.p.h / 2 + 1, Q.SPRITE_DEFAULT).; // si estamos en terreno y hay un acantilado si (nextTile & amp;! & Amp; tierra) {if (this.p.vx & gt; 0) {if (this.p.defaultDirection == «derecho») {este .p.flip = «x»; } Else {this.p.flip = false; }} Else {if (this.p.defaultDirection == «izquierda») {this.p.flip = «x»; } Else {this.p.flip = false; }} This.p.vx = -this.p.vx; }} 1234567891011121314151617181920212223242526step:. Función (dt) {vardirX = this.p.vx / Math.abs (this.p.vx); varground = Q.stage () localizar (this.px, this.p.y + esto. ph / 2 + 1, Q.SPRITE_DEFAULT); varnextTile = Q.stage () localizar (this.p.x + DirX * this.pw / 2 + DirX, this.p.y + this.ph / 2 + 1. , Q.SPRITE_DEFAULT); // si estamos en terreno y hay una cliffif (nextTile & amp;! & amp; tierra) {if (this.p.vx & gt; 0) {if (this.p.defaultDirection == «derecho» ) {this.p.flip = «x»;} else {this.p.flip = false;}} else {if (this.p.defaultDirection == «izquierda») {this.p.flip = «x» ;} else {this.p.flip = false;}} this.p.vx = -this.p.vx;}}

        Enemies en JSON

        La escalabilidad (la capacidad de crecer sin volverse loco) es un aspecto a tener en cuenta. Queremos ser capaces de crear rápidamente múltiples enemigos y no tener que crear las instancias individuales, uno por uno.

        Además, existe la posibilidad de que podemos desear para cargar los parámetros de nivel de Internet, en cuyo caso tenemos que ser capaces de material de carga de un objeto JSON.

        Sólo voy a mostrar una forma rápida para cargar los enemigos de nivel utilizando JSON. Se podría cargar una gran cantidad de otros parámetros de esta manera, y este objeto JSON podría provenir de Internet, el almacenamiento local, etc. El siguiente código de inicialización va dentro de nuestra level1, y utiliza un método Quinto etapas que han llamado “loadAssets”:
        // activos de nivel. formato debe ser como se muestra: [[NombredeClase, params], ..] levelAssets var = [[ «GroundEnemy», {x: 18 * 70, y: 6 * 70, activo: «slime.png»}], [» VerticalEnemy «{x: 800, y: 120, rangey: 70, activo: «fly.png»}], [ «VerticalEnemy», {x: 1.080, Y: 120, rangey: 80, de activos:» fly.png «}], [» GroundEnemy», {x: 6 * 70, y: 3 * 70, activo: «slime.png»}], [ «GroundEnemy», {x: 8 * 70, y: 70, de activos: «slime.png»}], [ «GroundEnemy», {x: 18 * 70, y: 120, activo: «slime.png»}], [ «GroundEnemy», {x: 12 * 70, y: 120, activo: «slime.png»}]]; // activos de nivel de carga stage.loadAssets (levelAssets); 12345678910111213 activos // nivel. formato debe ser como se muestra: [[NombredeClase, params], ..] varlevelAssets = [[ «GroundEnemy», {x: 18 * 70, y: 6 * 70, activo: «slime.png»}], [ «VerticalEnemy «, {x: 800, y: 120, rangey: 70, activo: «fly.png»}], [ «VerticalEnemy», {x: 1.080, Y: 120, rangey: 80, de activos: «fly.png» }], [ «GroundEnemy», {x: 6 * 70, y: 3 * 70, activo: «slime.png»}], [ «GroundEnemy», {x: 8 * 70, y: 70, activo:» slime.png «}], [» GroundEnemy», {x: 18 * 70, y: 120, activo: «slime.png»}], [ «GroundEnemy», {x: 12 * 70, y: 120, de activos : «slime.png»}]]; // nivel de carga assetsstage.loadAssets (levelAssets);

        sugerido Actividades

        Hemos llegado al final de este tutorial y antes de cerrar esto me gustaría sugerir algunas actividades que puede intentar por su cuenta:


        • Unir y participar de la comunidad Quinto Google Plus vibrantes
        • Añadir más tipos de enemigos
        • Cargar los enemigos JSON y archivos TMX nivel desde una ubicación remota.
        • Compartir Volver a la comunidad los componentes reutilizables que han creado.

          ¿Qué más Material para verificar

          Si te gusta mi estilo de enseñanza, en Zenva tenemos dos cursos de vídeo de alta calidad en el desarrollo de juegos HTML5 donde construimos varios ejemplos de diferentes tipos de juegos, como una vista superior disparar chicos malos juego al estilo Zelda, juegos de naves espaciales, la agricultura juegos, juegos de mascotas virtuales y muchos otros ejemplos!


          Mensajes relacionados

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *