Tiles y mapeado

Wednesday, July 19th, 2006 @ 23:20 | Nessi, Proyectos

En el post anterior, comentaba la existencia de problemillas varios con el sistema de carga de mapas de Nessi Engine. La principal traba es que al ser un fichero de texto (para facilitar la edición del mapa a mano, desde un bloc de notas mismamente) hay que leerlo como tal. Una primera opción es leer caracter a caracter, quedándome sólo con los números (que han de ser de una cifra). La función standar get(), hace esa función, pero devuelve ese char como unsigned char convertido a integer, es decir, el código ascii del caracter leido. (Si lee un cero, por ejemplo, file_map.get() devuelve un 48 ). Jugando con el código ascii y restando 48 al número sacado, la conversión al número leido estaba hecha. (por ejemplo, 48-48=0, lo que habíamos leido). Hasta ahí bien, pero eso da sólo 10 combinaciones posibles o, mejor dicho, sólo puedo tener en el array de recursos 10 frames, para poder referenciarlos a todos (su índice, del 0 al 9, pues para que lo anterior funcione en el fichero solo puede haber números de una cifra). Esto se queda corto, 10 frames para confeccionar mapas interesantes es bastante escaso. Intentando tirar del hilo, también podría utilizar las letras, y nuevamente hacer esa conversión a un número restando al ascii. Con varios ifs controlaría en que rango está, y en función de eso, restaría un número al otro. (de 48 a 57, restaría 48 y de 65 (A) a 90 (Z), restaría 55). Si además se incluyen las minúsculas, tendría un mayor número de recursos posibles a referenciar. (Ahora en el fichero, no sólo habría numeros, sino letras que la función SetLevel se encargaría de pasar a números válidos). Pero a pesar de todo, sigue resultando algo escaso, con unos 50 o 60 recursos a tener como máximo. Igual puede que este sistema nunca se me quede corto, pero nunca me ha gustado tener este tipo de limitaciones, así que toca cambiar de estrategia o filosofía.

Algo claro es que el fichero ha de seguir un patrón, tanto para que siga siendo fácilmente editable como para que la función que lea el fichero pueda interpretarlo sin demasiados problemas. Tener por ejemplo 1 45 234 en el fichero, no sería apropiado para este planteamiento. Sin embargo, un buen formato sería 000.000.000…. es decir, grupos de 3 caracteres (numéricos) y un punto de separación entre grupos. Este punto sólo sirve para facilitar esa edición, viendo de forma clara la separación entre grupos. El fichero, además, conserva las 20 columnas (cada columna ahora es cada grupo) y nos da un abanico de hasta 1000 recursos a referenciar, desde el 000 (que sería el 0) hasta el 999. El flamante fichero ya está definido, cumpliendo la premisa de seguir un mismo patrón. Ahora toca implementar la función que lo lea…

La función getline, presente en File input stream class o ifstream, lee una línea. Ahora, leer caracter a caracter no interesa, optando por ir leyendo línea a línea, tratándolas según son leidas. Por tanto, codificando file_map.getline(linea,81);, se obtiene toda una línea ( 000.000.000…..) y se almacena en la variable linea. Con un bucle for, se lee por partes esa línea sacada… for(j=0;j<80;j+=4). Incremento la i en 4, pues es el tamaño de los grupos. Dentro del bucle, se trata caracter a caracter cada grupo, eliminando los ceros a la izquierda, a través de dos ifs. Si linea[j]=0, significa que prescindiremos de ese dígito, fijandonos en el siguiente, linea[j+1]. Si éste también es cero, sólo nos quedaremos con la última cifra del grupo, linea[j+2]. Pero sigue siendo necesario tener un int, para el índice del array de recursos. La función atoi(), presente en stdlib.h, convierte una cadena de caracteres en una variable de tipo integer. Si se logra tener una cadena que contenga el número en un formato adecuado para ser convertido, tendremos solucionado el problema. Es obvio que si los grupos son de 3 digitos, el número mayor después de quitar los ceros a la izquierda, será de 3 digitos. Teniendo un array como char catet[4];, podremos almacenarlo en forma de cadena. (3 posiciones para los digitos y otra para el fin de cadena o \0). Por ejemplo, en el caso que un grupo sea como 005

catet[0]=linea[j+2]; // Paso el último digito del grupo
catet[1]=’\0′; // Añado el final de cadena
num=atoi(catet); // Convierto a integer

Y una vez generado num para todos los casos (número de una, dos o tres cifras), se indica el frame a cargar en objeto MTile del nivel (st), st.AddFrame(maps.ArrayTiles[num].name);. Si en el fichero hay un 012, num valdrá 12, seleccionandose del array de recursos el elemento con índice 12. Si vale 000, num vale 0 y se selecciona el primer elemento, con índice cero, del susodicho array de recursos. La función donde se hace todo esto es bool SetLevel(MTile &st, MTile maps, char *level), que devuelve true si todo fue ok, o false en caso contrario. (comentada en el anterior post, como void).

Lo siguiente será implementar su scrolling… :P

Leave a Reply