En este artículo vamos a explicar cómo dibujar tiles en HTML5 Canvas y la API que nos proporciona el navegador para renderizar gráficos. Dibujar tiles es una tarea esencial 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 dibujar tiles en HTML5 Canvas y sus pequeñas sutilezas, utilizando HTML5 Canvas y JavaScript.
Qué son los tiles
En el mundo de los videojuegos, los tiles son una parte pequeña de una imagen mayor que se utilizan como bloques de construcción para crear escenarios, niveles y mundos enteros. Estas imágenes generalmente se organizan en una cuadrícula, permitiendo a los desarrolladores crear entornos de juego de manera eficiente y flexible.
Si observamos la siguiente imagen obtenida de https://incolgames.itch.io/dungeon-platformer-tile-set-pixel-art vemos que está compuesta por una cuadrícula 13×15 de pequeños tiles de tamaño 32×32 píxels. Colocando varios de estos pequeños tiles en un lienzo canvas podemos crear diferentes ambientes y decorados para nuestros juegos.
Ahora que sabemos qué son los tiles en HTML5 Canvas vamos a ver cómo podemos obtenerlos y llevarlos a nuestro lienzo.
Crear un lienzo canvas
Como es habitual, lo primero que necesitamos es configurar nuestro documento HTML con un elemento Canvas, el cual nos proporcionará una área gráfica para dibujar, comúnmente llamado lienzo canvas. Tambien vamos a añadir la imagen de los tiles a nuestro HTML y que utilizaremos para mostrar en el Canvas sólo el tile que queremos como si fuera un gráfico individual. El ejemplo básico sería el siguiente:
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Imagen tile en HTML5 Canvas</title>
<style>
canvas {
border: 1px solid #000;
}
</style>
</head>
<body>
<canvas id="miCanvas" width="640" height="320">Canvas no soportado</canvas>
<p><img id="mi_tileset" src="tileset.png"></p>
</body>
</html>
En este ejemplo hemos creado un lienzo HTML5 Canvas con las etiquetas <canvas></canvas>
y justo debajo añadimos nuestra imagen de tiles con los siguientes atributos:
- ID Es un identificador único para referirnos al lienzo desde JavaScript y dibujar en él
- width, height Son las dimensiones en píxeles de nuestro lienzo o ventana gráfica
- El texto entre las etiquetas sólo se mostrará si el navegador no soporta la tecnología de dibujo HTML5 Canvas
- La imagen que añadimos debajo del <canvas> tiene el ID «mi_tileset» que utilizaremos para referirnos a ella en JavaScript
NOTA: Observa que hemos creado un lienzo a un tamaño compatible con nuestros tiles de 32×32 píxeles. Es importante mantener siempre esta compatibilidad a la hora de dibujar nuestros tiles en el canvas y que se vean bien.
Dibujo de tiles en HTML5 Canvas
Para dibujar imágenes simples en HTML5 Canvas se utiliza la instrucción ctx.drawImage(imagen, x, y, width, height)
que dibuja una imagen en las coordenadas especificadas y con el ancho y alto especificado. Ahora vamos a añadir el recorte del tile que queremos mostrar a partir de nuestra imagen:
ctx.drawImage(imagen, sx, sy, sw, sh, x, y, width, height);
La explicación de esta instrucción es la siguiente:
imagen
: Objeto imagen que se va a dibujar en el canvas, puede ser un objeto<img>
,<video>
o<canvas>
(obligatorio).sx
: Coordenada (x) del punto de inicio del área de recorte en la imagen fuente (opcional, valor por defecto 0).sy
: Coordenada (y) del punto de inicio del área de recorte en la imagen fuente (opcional, valor por defecto 0).sw
: Ancho del área de recorte en la imagen fuente (opcional, valor por defecto el ancho total de la imagen).sh
: Altura del área de recorte en la imagen fuente (opcional, valor por defecto la altura total de la imagen).x
: Coordenada (x) en el canvas donde se va a dibujar la esquina superior izquierda del tile (obligatorio).y
: Coordenada (y) en el canvas donde se va a dibujar la esquina superior izquierda del tile (obligatorio).width
: Ancho del tile que se va a dibujar en el canvas (opcional, valor por defecto el mismo que la imagen original).height
: Altura del tile que se va a dibujar en el canvas (opcional, valor por defecto el mismo que la imagen original).
ctx.drawImage()
es muy versátil y permite dibujar imágenes proporcionando opciones para recortar, escalar y posicionar la imagen según sea necesario. Si no se especifica el área de recorte (sx
, sy
, sw
, sh
) o su tamaño (width
, height
) la función dibujará la imagen completa.
La fórmula para saber la posición de cada tile será la siguiente:
- Posición (x, y) en la cuadrícula * ancho/alto, siendo (0, 0) la esquina superior izquierda.
- La llave está en (sx = 10 * sw, sy = 8 * sh) = (320, 256)
Dibujo de tiles en HTML5 Canvas con JavaScript
Ahora vamos a crear el código JavaScript para dibujar varios tiles a partir de nuestra imagen y mostrarlos en el lienzo Canvas. Además vamos a jugar con el tamaño y dibujaremos los tiles el doble de grandes, por eso es importante la compatibilidad entre el lienzo canvas y nuestros tiles. Este código JavaScript vamos a insertarlo justo debajo de la etiqueta <img>
:
<script>
window.onload = function () {
// Obtener el elementos de dibujo Canvas
let canvas = document.getElementById("miCanvas");
let ctx = canvas.getContext("2d");
// Obtenemos el tileset
let imagen = document.getElementById("mi_tileset");
// Rellenamos el canvas con un tile "oscuro"
for (let x=0; x<canvas.width; x+=64) {
for (let y=0; y<canvas.height; y+=64) {
ctx.drawImage(imagen, 96, 96, 32, 32, x, y, 64, 64);
}
}
// Dibujamos un "suelo"
for (let x=0; x<canvas.width; x+=64) {
ctx.drawImage(imagen, 32, 0, 32, 32, x, 256, 64, 64);
}
// Añadimos objetos sobre el suelo
ctx.drawImage(imagen, 320, 352, 32, 32, 64, 192, 64, 64); // Bolsa oscura
ctx.drawImage(imagen, 352, 352, 32, 32, 192, 192, 64, 64); // Bolsa clara
ctx.drawImage(imagen, 288, 288, 32, 32, 384, 192, 64, 64); // Caja
ctx.drawImage(imagen, 320, 256, 32, 32, 384, 128, 64, 64); // Llave
ctx.drawImage(imagen, 384, 288, 32, 32, 576, 128, 64, 64); // Puerta
ctx.drawImage(imagen, 384, 320, 32, 32, 576, 192, 64, 64); // Puerta
ctx.drawImage(imagen, 64, 352, 32, 32, 128, 0, 64, 64); // Cadena corta
ctx.drawImage(imagen, 0, 352, 32, 32, 256, 0, 64, 64); // Cadena media
}
</script>
Como explicamos en el artículo sobre las imágenes, este código tiene un evento «onload» muy feo pero que en este momento es necesario, vamos a explicar cómo funciona:
- Carga de la página: La función
window.onload
se ejecuta cuando la página web se ha cargado completamente. Ahora mismo esto es necesario para asegurar que la imagen se ha cargado completamente antes de proceder a trabajar con ella en el Canvas. - Obtención del canvas y contexto de dibujo: Obtenemos el elemento <canvas> y su contexto de dibujo 2D.
- Obtención de la imagen: Obtenemos el elemento imagen mediante su ID.
- Relleno del canvas con tiles oscuros: Se recorre el canvas en pasos de 64 píxeles tanto en el eje (x) como en el eje (y) y se dibuja un tile «oscuro» de la imagen en cada posición del canvas.
- Dibujo del suelo: Se dibuja una serie de tiles de la imagen que representan el suelo, con una altura fija de 256 píxeles.
- Añadir objetos sobre el suelo: Se dibujan diferentes objetos sobre el suelo, como bolsas, cajas, llaves, puertas y cadenas. Cada objeto se dibuja en una posición específica del canvas utilizando diferentes partes de la imagen.
Al abrir el archivo HTML en un navegador deberías ver la imagen original que hemos añadido al HTML y en el lienzo canvas el siguiente decorado de tiles:
NOTA: Los bordes discontinuos son parte de la imagen original que se ha utilizado de ejemplo
Resumen de tiles en HTML5 Canvas
El uso de tiles en HTML5 Canvas forma parte del proceso creativo en el diseño de un videojuego. Además de cargar una gran cantidad de gráficos mediante una sola imagen, permite recortar, escalar, rotar y posicionar cada tile de forma independiente manteniendo el modelo original.
En este sentido la función ctx.drawImage()
del Canvas es extremadamente potente y versatil. Observa también cómo hemos jugado con los tamaños 32×32 píxels originales y su dibujo en el canvas a 64×64 píxels. Mantener la misma proporción es un detalle importante para obtener una buena calidad gráfica, porque con otros tamaños se ve peor.
En otro post explicaremos la forma de crear decorados enteros para nuestros videojuegos a partir de tilemaps o tilesets.
¡ Espero que este artículo sea de vuestro interés !