¡Buenas!

En esta entrada continuaré donde lo dejé la vez pasada, en la PARTE 1.

 

PARTE 2: Creando el motor

Vamos a dividir el código de nuestro juego en dos archivos: assets.js tendrá la programación de los recursos, y game.js la del juego en sí.

 

LOS SPRITES

Antes de comenzar a programar el juego en sí, vamos a necesitar crear algunos objetos que nos permitan reutilizar código para manejar los elementos del juego. Comenzaremos por los elementos más básicos: Los sprites.

 

Diremos que un sprite es una imagen en tira que posee un número determinado de “subimágenes”.

Por ejemplo, veamos esta imagen (mide 536x67):

Si creamos un sprite de 8 subimágenes usando esta imagen, concluiríamos que cada subimagen mediría 67x67. Lo que queremos conseguir es poder dibujar sólo una de las 8 subimágenes del sprite, cualquiera de ellas, utilizando un “índice”.

 

Necesitamos una función que nos permita crear un sprite con las propiedades anteriores:

//Esto iría en assets.js
function Sprite(src, number) {
    this.image = new Image();
    this.image.src = src;
    this.number = number;
}

Esta función en sí no es muy complicada. Lo que tenemos que hacer para crear un nuevo sprite, será crear una instancia de ésta dándole los dos parámetros que necesita: La URL (relativa al documento HTML) de la imagen del sprite, y el número de subimágenes que éste tendrá. Algo como:

var sprite = new Sprite('source/sprites/spr_player.png', 8);

 

Lo siguiente que tenemos que hacer será lo verdaderamente importante: Una función que tome las propiedades del sprite, y dibuje la subimagen indicada. Para ello utilizaremos el método drawImage() del CanvasRenderingContext2D.

//También iría en assets.js
function draw_sprite(render, src, index, x, y) {

    var frame_w = src.image.width / src.number; //El anchor de cada subimagen. Anchor total / número subimágenes
        index = index % src.number; //Limitar el índice dentro de cantidad de subimágenes.
        
    render.drawImage(
        src.image, //Imagen a dibujar
        frame_w * index, //Posición X desde la que se tomará la parte de la imagen que hay que dibujar
        0, //Posición X desde la que se tomará la parte de la imagen que hay que dibujar
        frame_w,  //Anchor de la parte de la imagen que se tomará
        src.image.height, //Altura de la imagen que se tomará
        x, //Posición x en el canvas donde dibujar la parte dada de la imagen
        y, //Posición x en el canvas donde dibujar la parte dada de la imagen
        frame_w, //Anchor con el que dibujar la parte dada de la imagen en el canvas
        src.image.height //Anchor con el que dibujar la parte dada de la imagen en el canvas
    );

}

Entendamos lo que hace esta función:

 

Lo primero que hace es calcular el tamaño de cada subimagen, tomando en cuenta el tamaño total de la imagen y la cantidad de subimágenes que habrán.

Después ajusta el índice dado para que quede entre 0 y la cantidad de subimágenes – 1. Por ejemplo (tomando en cuenta el mismo sprite), si el índice fuera 0, éste permanecería así. Si fuera 8, se convertiría en 0, y si fuera 9 se ajustaría a 1. De esta manera siempre se mantendrá en el rango adecuado.

 

Lo siguiente que se hace es dibujar una parte de la imagen (la subimagen) de acuerdo al índice y posición dados. En este enlace dejo la documentación del método.

Probemos cómo funciona nuestro dibujo de sprites:

 

En el archivo game.js, agreguemos un evento load, obtengamos el elemento canvas y su contexto, y dibujemos un sprite animado:

//Esto iría en game.js
window.addEventListener( 'load', function() {

    var canvas = document.getElementById('game');
    var render = canvas.getContext( '2d' );


    const sprite = {
        player: new Sprite('source/sprites/spr_player.png', 8)
    };

    var i = 0;
    window.setInterval( function() {

        render.clearRect( 0, 0, canvas.width, canvas.height );
        draw_sprite(render, sprite.player, i, 32, 32);
        i++;

    }, 1000 / 60);


} );

Y veamos lo que sucede: Observa el funcionamiento aquí.

 

Dejémoslo hasta aquí. Continuaré en la siguiente parte.

¡Saludos!