Anda di halaman 1dari 6

TEMPORADA 2.

SESIN 2

Creando un mapa con


los SpriteSheet
Desarrollando un juego en Java y Slick2D
danirod@outlook.com
www.danirod.tk
Versin v1.0, octubre de 2012

Este documento se publica bajo los trminos de la licencia Creative Commons 3.0 Atribucin No
Derivativos Espaa. Significa que eres libre de usar y distribuir este documento, incluso con fines
comerciales, siempre que indiques el autor de este documento y que lo distribuyas tal cual, sin
modificar su contenido.

Desarrollando un juego en Java y Slick2D Temporada 2, Sesin 2

Creando un mapa con los SpriteSheet


El objetivo de esta sesin es aprovechar la funcionalidad de los spritesheets para crear una
cuadrcula de tiles que pueda servir como un mapa. Al final de esta sesin, seremos capaces de
generar mapas bidimensionales sobre los que imprimir los diferentes sprites.
En el vocabulario ingls, cuando se utilizan spritesheets para construir mapas, en lugar de
sprites podemos llamarles tiles, y al spritesheet, le podemos llamar tilesheet. El resultado final
es un mapa que podemos llamar tilemap.

Cmo vamos a guardar la informacin de nuestro mapa


Nuestro mapa va a tener dos coordenadas: una coordenada X (horizontal) y otra coordenada Y
(vertical). Aparentemente, la forma ms cmoda de almacenar este tipo de datos es usando un
vector, en el que introduciremos los datos de cada posicin del tile, segn su valor X e Y.
Los datos del tile se corresponden con los valores X e Y del sprite que queremos obtener, por
ejemplo, (0,0) para obtener el sprite de la esquina superior izquierda, o (4,2) para obtener el
sprite situado en la quinta posicin empezando por la izquierda y en la tercera posicin
empezando por la parte superior.
Podemos usar cualquier mtodo para almacenar esos datos. Podemos obtener
automticamente el sprite y crear un array bidimensional de imgenes, podemos crear una
estructura de datos que permita almacenar de forma lgica los valores X e Y de cada sprite,
crear un tipo enumerado con los diferentes elementos que tenga nuestro spritesheet, o
simplemente podemos crear un array de enteros en el que la posicin 0 contenga el valor X del
sprite y la posicin 1 contenga el valor Y.
De modo que el array con la informacin del mapa ser en realidad un array tridimensional:
dos dimensiones destinadas a almacenar las casillas de nuestro mapa, y una tercera dimensin
que se destina a almacenar los datos de cada sprite, que son la posicin X y la posicin Y que
ocupan en nuestra hoja de sprites.

Creando un array de valores para nuestro mapa


Una forma muy sencilla y visual de crear este array es de forma constante, grabando esos
valores en el cdigo fuente. De modo que podemos escribir el siguiente cdigo:
private static final int[][][] MAPA = {
{, , , ,},
{, , , ,},
{, , , ,}
};

Este tipo de estructura es visual en tanto que podemos distinguir en nuestro cdigo fuente
cada una de las filas y de las columnas de nuestro mapa.

Cada fila del mapa se guarda en una lnea de cdigo distinta. Estas filas se
corresponden con la coordenada Y de nuestro mapa.
Dentro de cada fila, las comas separan cada columna del mapa. Estas columnas se
corresponden con la coordenada X del mismo.

Recordad bien que la primera dimensin guarda la coordenada Y y la segunda dimensin la


coordenada X. Cuando obtengamos luego los datos del mapa, tendremos que obtenerlos como
mapa[y][x], es decir, al revs de lo habitual (mapa[x][y]).
Simplemente tenemos que sustituir cada espacio en blanco de nuestro array MAPA con otros
array que contengan las posiciones X e Y de los diferentes sprites dentro de nuestra hoja de
sprites o spritesheet. Por ejemplo, sea un espacio en blanco un spritesheet que est en la
posicin (9,7) de la hoja. Para generar un array de sprites en blanco el resultado final de cdigo
ser:
private static final
{{9,7}, {9,7},
{{9,7}, {9,7},
{{9,7}, {9,7},
};

int[][][] MAPA = {
{9,7}, {9,7},},
{9,7}, {9,7},},
{9,7}, {9,7},}

A partir de este momento, slo tenemos que cambiar las coordenadas que nos interesen por
valores reales que contengan imgenes de verdad. Lo dems queda a cosa nuestra.

Procesando el mapa lgico para generar un mapa de imgenes


El siguiente paso es crear otro array que tenga solamente dos dimensiones. Este mapa
almacenar directamente las imgenes que mostraremos en la pantalla, por lo que no
necesitamos la dimensin de coordenadas.
Generar este procesador es tan fcil como construir un mtodo que recorra las dimensiones X
e Y de nuestro mapa lgico y que vaya guardando el sprite situado en las dimensiones que
indica la tercera dimensin.
En primer lugar tenemos que construir ese mapa de imgenes, obteniendo las dimensiones del
mapa de imgenes a partir de las dimensiones que tenemos almacenadas en nuestro mapa
lgico.
private Image[][] imagenes;
// ...
int x = MAPA[0].length;
int y = MAPA.length;
imagenes = new Image[x][y];

Ahora simplemente tenemos que crear el procesador, para lo cual recorreremos una a una las
posiciones del mapa de imgenes, y para cada una de esas posiciones importaremos un sprite
sacando sus dimensiones del mapa lgico. Recorrer el array es tan fcil como:
for(int x = 0; x < imagenes.length; x++) {
for(int y = 0; y < imgenes[0].length; y++) {
}
}

Y dentro introducimos la imagen recuperando los datos de esa posicin:


SpriteSheet spritesheet;
// ...
for(int x = 0; x < imagenes.length; x++) {
for(int y = 0; y < imgenes[0].length; y++) {
int tilex = MAPA[y][x][0];
int tiley = MAPA[y][x][1];
imagenes[x][y] = spritesheet.getSprite(tilex, tiley);
}
}

Esta funcionalidad la podemos introducir dentro de un mtodo. El resultado de ejecutar este


mtodo ser tener un array con las diferentes imgenes que contiene el mapa.

Mostrando ese array de imgenes en pantalla


Ahora slo nos queda rellenar un mtodo draw() que al ser llamado dibuje el mapa en la
pantalla. En realidad, este proceso de dibujado de mapa consistir en dibujar en posiciones
concretas todos los tiles que componen el mapa.
Como sugerencia, la clase que contenga el mtodo draw() puede indicar que est
implementando la interfaz de Slick Renderable. Con esto, se asegura la existencia de un
mtodo draw(float x, float y). La contrapega de implementarla es que nuestro mtodo
no podr lanzar ninguna excepcin, puesto que la interfaz lo exige as. De modo que el
tratamiento de excepciones deber ser tratado y neutralizado dentro de la propia clase.
public void draw(float origenx, float origeny) {
for(int x = 0; x < imagenes.length; x++) {
for(int y = 0; y < imagenes[0].length; y++) {
Image esteSprite = imagenes[x][y];
// TODO: dibujar esteSprite en pantalla
}
}
}

Como se ve, terminaremos por reducir el proceso de dibujar el mapa a dibujar de manera
individual cada sprite en pantalla. Tenemos que usar las matemticas para obtener las

coordenadas X e Y en las que dibujaremos cada uno de esos sprites. Este puede ser el proceso
ms complicado de todos en algunos casos.

Son origenx y origeny las coordenadas de la esquina superior izquierda del mapa.
Todos los sprites se dibujarn a la derecha (coordenada X mayor) de origenx, y
debajo (coordenada Y mayor) de origeny.
Son ancho y alto las dimensiones de cada uno de los sprites. Todos los sprites tienen la
misma dimensin. En este sentido, ancho y alto actuarn como constantes para
indicar el ancho y el alto de cualquier sprite.
Sea x la posicin horizontal del sprite con el que estamos trabajando. Este nmero est
comprendido entre 0 y el tamao horizontal del array de imgenes menos uno.
Sea y la posicin vertical del sprite con el que estamos trabajando. Este nmero est
comprendido entre 0 y el tamao vertical del array de imgenes menos uno.

Cada sprite deber ser dibujada en una posicin que est basada en (origenx, origeny), pero
que est desplazada un nmero de pxeles con respecto a esas coordenadas de origen.
Supongamos la coordenada horizontal. Este desplazamiento ser proporcional a la coordenada
horizontal del tile dentro del mapa. As, el tile que est en la posicin x=0 no tendr que estar
desplazado, pero el tile de la posicin x=1 tendr que estar desplazado hacia la derecha un
nmero de pxeles para aparecer junto al tile anterior, y as sucesivamente. Adems, para que
el dibujo se vea correctamente, ese nmero de pxeles que se desplaza deber ser igual al
tamao horizontal de un tile. De este modo, al poner un tile junto a otro, se vern sin espacios
entre medias ni sin solapar otros tiles.
Por lo tanto, la posicin final ser pixelx = origenx + desplazamiento, y ese
desplazamiento ser proporcional al nmero de tile con el que estemos trabajando en esa
coordenada y a las dimensiones del tile, es decir, desplazamiento = x * ancho.
Podemos aplicar esa misma idea a la coordenada vertical, y obtendremos que las coordenadas
a las que dibujaremos cada tile son:
float coordx = origenx + x * ancho;
float coordy = origeny + y * alto;

El mtodo de dibujo final una vez se ha construido todo ser:


public void draw(float origenx, float origeny) {
int ancho = imagenes[0][0].getWidth();
int alto = imagenes[0][0].getHeight();
for(int x = 0; x < imagenes.length; x++) {
for(int y = 0; y < imagenes[0].length; y++) {
Image esteSprite = imagenes[x][y];
float coordx = origenx + x * ancho;
float coordy = origeny + y * alto;
esteSprite.draw(coordx, coordy);
}
}
}

Con esto queda terminado nuestra clase de mapa. Podemos crear una instancia de esta clase
mapa en nuestro estado de juego y podremos comprobar su funcionamiento:
public class Estado extends BasicGameState {
private Mapa mapa;
public void init(GameContainer container, GameState state)
throws SlickException {
mapa = new Mapa();
}
public void draw(GameContainer container, GameState state,
Graphics g) throws SlickException {
mapa.draw(0, 0);
}
public void render(GameContainer container, GameState state,
int delta) throws SlickException {}
public int getID() { return 0; }
}

Anda mungkin juga menyukai