Cargador de imágenes JavaScript

En este artículo vamos a explicar cómo crear un cargador de imágenes JavaScript para guardarlas y usarlas en nuestros videojuegos. Tener un cargador de imágenes es un aspecto fundamental en la programación de videojuegos y forma parte de los artículos siguientes:

  • Imágenes en HTML5 Canvas: En este artículo aprenderemos a mostrar una imagen ya existente en el lienzo Canvas
  • Tiles en HTML5 Canvas: En este artículo aprenderemos a mostrar sólo una parte de una imagen ya existente en el lienzo Canvas
  • Sprites en HTML5 Canvas: En este artículo aprenderemos a crear y dibujar un Sprite (imagen animada) de una imagen ya existente en el lienzo Canvas
  • Cargador de imágenes JavaScript: En este artículo aprenderemos a cargar de forma dinámica cualquier imagen que necesitemos dibujar en nuestro lienzo Canvas

En este artículo, vamos a explicar cómo cargar imágenes con JavaScript y guardarlas para su uso posterior de forma dinámica.

¿ Porqué un cargador de imágenes ?

Disponer de un cargador de imágenes en JavaScript es una herramienta fundamental a la hora de desarrollar nuestros videojuegos con HTML5 y Canvas. Como ya vimos en artículos anteriores, necesitábamos utilizar la fea función window.onload para asegurarnos que se habían cargado completamente las imágenes en la página HTML antes de trabajar con ellas. En caso contrario no se mostraría nada.

Ahora vamos a crear una función que nos permite realizar la carga de todas las imágenes que necesitemos de forma asíncrona. Capaz de avisarnos si detecta errores en la carga de las imágenes y, una vez cargadas todas las imágenes, ejecutar una función.

Esto es justo lo que realizan todos los videojuegos antes de ejecutarse mientras en la pantalla se muestra un mensaje del tipo «LOADING … «

Cargador de imágenes con JavaScript

Nuestro cargador de imágenes JavaScript lo que va a realizar es la precarga de las tres imágenes utilizadas en los artículos anteriores (nave.png, tileset.png, enemy-sprite.png). Pero esta vez las cargaremos con JavaScript y no las añadiremos a la página con la etiqueta <img>. El código completo es el siguiente.

<!DOCTYPE html>
<html lang="es">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Precarga de imágenes con JavaScript</title>
  <style>
    canvas {
      border: 1px solid #000;
    }
  </style>
</head>
<body>
  <canvas id="miCanvas" width="800" height="600">Canvas no soportado</canvas>
  <script>
    // Obtenemos datos del Canvas
    let canvas = document.getElementById("miCanvas");
    let ctx = canvas.getContext("2d");

    // Variables para cargar imágenes
    let imgTotal = 0;
    let imgIndex = 0;
    let imgLibrary = [];  
    let imgCallback = function(){};      

    // Precarga de imágenes
    function load(name, url, callback) {
      imgTotal++;
      if (callback) imgCallback = callback;
      let img = new Image();
      // Debe ponerse antes
      img.onload = function() {
        imgIndex++;
        if (imgTotal == imgIndex) imgCallback();    
      }
      // Manejo de errores
      img.onerror = function() {
        alert('Error cargando imagen: '+url);
        imgIndex++; // Aumenta el índice aunque haya un error para no quedar bloqueado
        if (imgTotal == imgIndex) imgCallback(); 
      }      
      img.src = url;
      imgLibrary[name] = img;
    }	

    // Precarga las imágenes
    load('nave', 'nave.png');
    load('tileset', 'tileset.png');			
    load('sprite', 'enemy-sprite.png', animateScene);	          
  
    // Bucle universal de animación
    function animateScene() {	
      for (let key in imgLibrary) {
        let x = Math.floor(Math.random() * (canvas.width - 100));
        let y = Math.floor(Math.random() * (canvas.height - 100));
        ctx.drawImage(imgLibrary[key], x, y);       
      }
      requestAnimationFrame(animateScene);
    }
  </script>
</body>
</html>

Explicación del código JavaScript

Con este código JavaScript creamos un cargador de imágenes asíncrono para luego dibujarlas en un canvas HTML5. La explicación detallada de su funcionamiento es el siguiente:

  • Obtención del canvas y su contexto: Obtenemos el elemento <canvas> y su contexto de dibujo 2D.
  • Variables para la carga de imágenes: Se inicializan varias variables para gestionar la carga de imágenes:
    • imgTotal: Un contador que registra el número total de imágenes que se están cargando.
    • imgIndex: Un contador que registra cuántas imágenes se han cargado correctamente.
    • imgLibrary: Un objeto que actúa como una librería donde se almacenan las imágenes cargadas utilizando un nombre como clave.
    • imgCallback: Una función de devolución de llamada que se ejecutará una vez que todas las imágenes se hayan cargado correctamente.
  • Función de precarga de imágenes (load): La función (load) toma tres argumentos: name (nombre de la imagen), url (URL de la imagen) y callback (función de devolución de llamada, opcional). Dentro de la función (load) se ejecutan las siguientes acciones para cada imagen:
    • Se incrementa (imgTotal) para contar una nueva imagen que se está cargando.
    • Si existe, se toma la función de devolución de llamada (callback) y se asigna a (imgCallback).
    • Se crea un nuevo objeto de imagen utilizando new Image().
    • Se establece el evento (onload) en el objeto de imagen. Esta función se ejecutará automáticamente cuando la imagen se cargue correctamente.
    • Se establece el evento (onerror) en el objeto de imagen. Esta función se ejecutará automáticamente si hay un error al cargar la imagen.
    • Se asigna la URL de la imagen al atributo (src) del objeto de imagen.
    • Se almacena la imagen en el objeto (imgLibrary) con el nombre proporcionado como clave.
  • Precarga de imágenes: Se llama a la función (load) tres veces para cargar tres imágenes: «nave.png», «tileset.png» y «enemy-sprite.png». La tercera llamada a (load) también proporciona la función (animateScene) como una función de devolución de llamada. Esta función será ejecutada una vez cargadas todas las imágenes.
  • Función de animación (animateScene): La función (animateScene) se llama indefinidamente repetidamente utilizando (requestAnimationFrame). Dentro de (animateScene) se ejecutan las siguientes acciones:
    • Se itera sobre todas las imágenes de (imgLibrary).
    • Se genera una posición aleatoria (x, y) dentro del canvas.
    • Se dibuja cada imagen en la posición (x, y) utilizando ctx.drawImage() lo que significa que todas las imágenes se dibujan en posiciones aleatorias en el canvas indefinidamente.

Resumen del cargador de imágenes JavaScript

Al abrir el archivo HTML en un navegador deberías ver una sucesión de imágenes superpuestas, en un bucle contínuo, parecido a la siguiente imagen:

Cargador de imágenes JavaScript
Cargador de imágenes JavaScript

Antes de iniciarse cualquier juego, se deben cargar los diferentes recursos gráficos, sonidos, controladores, etc. que van a conseguir mover el juego con soltura. Por eso es imprescindible contar con una herramienta capaz de cargar todas nuestras imágenes antes de ejecutar el juego y sólo entonces, iniciar el juego.

Con este cargador de imágenes JavaScript asíncrono, podemos conseguirlo y posteriormente utilizar las imágenes cargadas con el nombre que le hemos asignado. Un código que es súmamente útil también en otro tipo de aplicaciones.

¡ Espero que este artículo sea de vuestro interés !

Deja un comentario