En el tutorial de hoy, vamos a empezar con la primera parte para realizar un juego fenomenal en JavaScript. Este post es una de las muestras de que este lenguaje de programación es sumamente vérsatil, fácil de aprender, y te ayudará a simplificar muchos aspectos de tu código. Así que, sin mas que decir ¡Comencemos!
Paso 1: Comenzando con un fondo animado
Realmente quería escribir un tutorial sobre una tecnología de juegos que me gusta usar, así que aquí está. En esta historia, vamos a empezar a hacer un pequeño juego de shoot’em up con PixiJS, una biblioteca de Javascript muy simple y genial.
Lo que vamos a hacer exactamente es hacer una nave espacial capaz de moverse y disparar, olas enemigas entrando y un hermoso fondo animado con nubes en movimiento. La primera parte (esta que lees ahora) se centrará en los antecedentes.
¿Cómo empezar?
Comencemos por poner en marcha nuestro proyecto: He subido una estructura de código ya establecida, así que todos estamos trabajando con la misma base. Sin embargo, si quieres hacerlo tú mismo, puse una foto de mi carpeta justo debajo:
Clic aquí para descargar tu carpeta
Necesitaremos un servidor local para ejecutar el juego: Te invito a descargar WAMP si estás trabajando con Windows, o MAMP para macOS, son gratuitos y fáciles de usar. Vamos a poner tu carpeta de juegos en el servidor (htdocs for MAMP / www for WAMP) y teclear el enlace localhost en tu navegador favorito (para mí sería: http://localhost:8888/Spaceship/bin/)
En index.html, estamos importando los archivos javascript del encabezado:
<script src="../src/lib/pixi.min.js"></script> <script src="“../src/main.js”"></script>
… y necesitamos hacer lo mismo para cada archivo que hacemos. Luego viene la inicialización de Pixi (que se basa en el motor de renderizado WebGL):
var renderer = PIXI.autoDetectRenderer(window.innerWidth, window.innerHeight);
Para este tutorial, le decimos al juego que cubra toda la ventana del navegador, así que si lo intentas ahora obtendrás un fondo totalmente negro.
El archivo main.js es el lugar donde comienza todo el juego. Es como un manager, con la primera función ejecutada del juego, y el bucle donde podemos decirle al juego lo que tiene que hacer en cada cuadro. Lo que queremos es un fondo azul para el cielo cuando empiece el juego, así que vamos a actualizar la función init:
function init() { renderer.backgroundColor = 0x22A7F0; renderer.render(stage); loop(); }
Pixi está usando el formato de color hexadecimal, así que necesitas escribir tu código de color precedido por 0x. ¡Guardemos y veamos el resultado en su navegador!
¡Nubes por todas partes!
Este fondo es muy aburrido, agreguemos algunas nubes flotantes.
Primero, agreguemos un nuevo archivo de la clase CloudManager en la carpeta src (el cual va a crear y mover las nubes).
class CloudManager { constructor() { } update() { } }
No olvides añadirlo en el archivo index.html como hicimos para main.js:
<script src="../src/lib/pixi.min.js"></script> <script src="../src/CloudManager.js"></script> <script src="../src/main.js"></script>
El constructor es el punto de entrada de esta clase donde podemos añadir la función spawn para nuestras nubes. Lo que queremos es básicamente un método capaz de crear una nube cada X segundos, y está perfecto porque hay una cosa de javascript para esto:
window.setInterval(function() { } , 1000);
Este pedazo de código, colocado en el constructor, llamará a lo que está dentro de los soportes del juego cada 1000 milisegundos (= 1 segundo).
Añadamos sprites de nubes en la carpeta de activos, y como es mejor tenemos 2 imágenes diferentes: (las nubes son blancas con fondo transparente por lo que eran invisibles en esta página, pero aquí están los enlaces en GitHub:
Necesitamos cargar los sprites antes de que empiece el juego, así que añádelos en la función Pixi.loader.add:
PIXI.loader.add([ "assets/cloud_1.png", "assets/cloud_2.png" ]).load(init);
Ok, ahora podemos mostrar las nubes en el método setInterval del CloudManager:
window.setInterval(function() { const sprite = (Math.random() > 0.5 ? "cloud_1" : "cloud_2"); this.cloud = new PIXI.Sprite(PIXI.loader.resources["assets/" + sprite + ".png"].texture); this.cloud.anchor.set(0.5, 0.5); this.cloud.position.set(renderer.width * 1.2, renderer.height * Math.random()); stage.addChild(this.cloud); } , 1000);
Para reanudar este código:
- Primero, estamos calculando un número aleatorio entre 0 y 1, y o bien es inferior a 0,5, por lo que almacenamos el primer sprite en una constante, o bien es el segundo.
- Luego, creamos un nuevo objeto sprite con la imagen que obtuvimos en la línea anterior.
- El punto de origen de este sprite va a ser su esquina superior izquierda, por lo que fijamos su punto de anclaje en el centro.
- Tenemos que mostrar la nube más allá del borde derecho de la pantalla, para que pueda moverse a la izquierda a través de la pantalla: renderer.width * 1.2 es la posición del borde izquierdo + el ancho de la pantalla + 20% de su ancho. Podemos estar seguros de que no lo veremos desovando. Para la posición y, renderer.height * Math.random() es un número entre 0 y la altura de la ventana. Por lo tanto, la posición vertical de la nube se ubicará entre la parte superior e inferior de la pantalla.
- Por último, añadimos esta nube a la escena.
Si ejecuta este código, no debería aparecer nada, y es a propósito porque tienen que desaparecer de la vista. Así que ahora tenemos que hacer que se muevan.
La función de actualización es el lugar para hacerlo. Pero necesitamos almacenar las nubes en un array para poder iterar y establecer sus posiciones. Inicialicemos una nueva matriz en el constructor de CloudManager:
this.cloudsList = [];
… y empuja las nubes hacia adentro después de la función stage.addChild:
this.cloudsList.push(this.cloud);
Ahora podemos iterar el array en actualización y establecer la posición de cada nube:
this.cloudsList.forEach(function(element) { element.position.x -= 4; });
¡Ahora debería estar funcionando!
Oh, espera, algo debería molestarnos: ¿adónde van todas esas nubes?
Sí, si no los eliminamos después de que salieron de la pantalla, seguirán existiendo y puede causar algunos problemas de rendimiento. Añadamos una declaración de forEach para cada uno de ellos que los borre cuando su posición horizontal sea un poco inferior al borde izquierdo de la pantalla (así que no podemos verlos saliendo):
if (element.position.x < -renderer.width * 0.3) { element.destroy(); array.splice(0, 1); }
¡Hemos terminado con las nubes!
¿Qué hay de hacer una variación aleatoria en el tamaño de las nubes? Añade esto al bloque de creación de nubes:
let minScale = 0.2; let maxScale = 1.2; let scale = Math.random() * (maxScale - minScale) + minScale; this.cloud.scale.set(scale, scale);
Si te falta algo o no funciona en tu código, puedes comprobar el resultado aquí.
Ahora continúa a la próxima parte para finalizar nuestro primer juego en JavaScript. ¡Sigue adelante!