sábado, 14 de marzo de 2009

Clases básicas: TileSet

TileSet es una clase que nos permite trabajar con los tiles. Los tiles son esas pequeñas imágenes, de 8x8 pixeles, que sirven para dibujar en las pantallas de la nintendo DS.

Para explicarlo mejor, las pantalla de la DS tienen 256x192 pixeles. Dividido entre 8 nos da 32x24 casillas. Es decir, cada pantalla tienen 32x24 casillas, y en cada casilla se puede dibujar un tile.

PaLib nos permite trabajar con estos tiles de una forma muy sencilla, pero la clase TileSet nos permite aún una mayor abstracción. Sólo contiene, por ahora, tres funciones.

El constructor de la clase nos permite cargar en memoria la imagen con todos los tiles de nuestro juego.

La función SetTile16x16 nos permitirá dibujar en una ubicación dada un tile.

La función GetTile nos permite ver que tile hay en una ubicación dada. Esto nos servirá para el tema de colisiones.

Esta es la imagen que usamos, en este momento, en el proyecto:



Si os fijáis bien el primer rectángulo es rosa, eso significa que el 0 será un recuadro transparente.

Un ejemplo de uso:

#define PLATAFORMAS (void *)plataformas_Pal, (void *)plataformas_Tiles, SIZEOF_16BIT(plataformas_Tiles), (void *)plataformas_Map

#define COLUMNAS_16x16_PANTALLA 16
#define COLUMNAS_16x16_MAPA 48
#define FILAS_16x16 12
#define MAPA_PLATAFORMAS (void *)mapa, COLUMNAS_16x16_PANTALLA, FILAS_16x16, COLUMNAS_16x16_MAPA

int mapa[COLUMNAS_16x16_MAPA * FILAS_16x16] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 5, 2, 4, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7, 12, 8, 11, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7, 8, 13, 12, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7, 12, 8, 11, 14, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7, 11, 12, 13, 14, 0, 0, 0, 0, 0, 0, 7, 9, 8, 10, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7, 12, 13, 8, 14, 0, 0, 0, 0, 0, 0, 7, 12, 10, 13, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7, 13, 9, 10, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 3, 2, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7, 12, 8, 12, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7, 8, 12, 13, 15, 4, 3, 3, 4, 2, 3, 4, 2, 5, 4, 4, 3, 5, 2, 3, 5, 4, 3, 3, 4, 2, 3, 4, 2, 5, 4, 2, 3, 5, 2, 3, 5, 4, 3, 3, 4, 2, 3, 4, 2, 5, 4, 6,
7, 11, 13, 12, 8, 10, 9, 11, 12, 11, 8, 12, 12, 13, 12, 8, 10, 9, 11, 12, 11, 8, 12, 9, 11, 12, 11, 8, 12, 9, 13, 12, 8, 10, 9, 11, 8, 12, 12, 13, 12, 10, 12, 11, 8, 12, 9, 14
};

TileSet *newTileSet = new TileSet(SCREEN_TOP, BACKGROUND_TWO, PLATAFORMAS);
newTileSet->SetTile16x16(MAPA_PLATAFORMAS, 10, 10);

Es muy sencillo. Me gusta usar los defines, porque el código queda mucho más claro, desaparecen * y (void *) y queda todo más cómodo.

Saludos

3 comentarios:

David Martínez Martínez dijo...

¡Me gusta la forma en la que lo estás enfocando! Lo de una clase solo para tiles, y ahí todos los gráficos puestos en una sola imagen, me recuerda a la programación de toda la vida, con una sola imagen con todos los gráficos ahí apretados, para gastar lo mínimo de memoria.

Por cierto, a la hora de hacer las fases para el juego, ni se te ocurra hacerlo en modo texto. Una solución sería hacer una aplicación para PC, en java, C# o lo que tu quieras, que sea gráfica. Y cuando tengas la fase como quieras, le digas, generar texto, y el solo te cree los defines, que tu copias y pegas donde quieras.

Hacer esta aplicación no es complicado, y te facilita el trabajo una barbaridad.

¡Sigue así! Estás haciendo algo que la gente no sabe hacer, ni en cursos de programación de videojuegos de pago. ¡Y gratis! xD

Cuídate.

Inigo dijo...

Gracias David, aunque creo que exageras un poco...

Tengo empezado algo en Java, pero ahora estoy muy ocupado y apenas puedo dedicar tiempo. Aún así, intentaré ser puntual a mi cita de los viernes.

Saludos

David Martínez Martínez dijo...

Te puedo asegurar que he visto temarios de cursos, de XNA game studios para programar en xbox360, de directx 9 de pago, programación de videojuegos para DS...

Y la primera vez que vi poner SCREEN_TOP en vez de 1, por ejemplo, fue en tu código. Algo que hace mucho más visible tu código, en los demás tutoriales no se molestan en hacer esas cosas, porque es algo que "debemos saber". Van a lo "importante", como hacer un engine 2d en solo una semana y cosas así.

Cuando en la programación, y más en proyectos complejos, lo mejor es establecer una buena base y unas buenas prácticas, para a partir de ahí desarrollar lo aprendido y establecer objetivos claros y factibles. Como me decía un profesor mío de primero de carrera, "divide y vencerás".

Te puedo asegurar que he llegado a ver verdaderas BURRADAS en código de cursos de pago (que yo no pagué pero sí conseguí los apuntes como pude), cosas tan sencillas como la tabulación.

Y me parece que estoy igual que tu, me quedo con muchas ganas de seguir tu tutorial más de cerca, pero... Trabajo, trabajo, trabajo...

¡A ver si me pongo y puedo ayudarte a profundizar en otras cosas! ¡Aún no me olvidé del DSfit! xD Saludos