Tilemap Editor v2

Started by Drumpi, March 02, 2016, 08:12:27 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Drumpi

He tenido un parón con el programa. No me preguntéis qué ha pasado porque ahora mismo ni yo me acuerdo ^^U
No sé si será la pasada Game Jam, seguido de unos días de esquí (uno de los dos periodos anuales en los que hago ejercicio :P ) y quedarme tranquilo en casa con la Feria, pero llevo un par de días que no paro.

He conseguido terminar la lista lateral de mapas abiertos. A lo que ya tenía se le ha sumado que ya se puede hacer scroll por la lista usando los botones, que aparezca el nombre de los mapas abiertos (no sólo la de los mapas nuevos), y que se actualicen si se guardan con otro nombre.
Que esa es otra, creía que ya había hecho las funciones para guardar los mapas, y resulta que no, que lo que tenía hecho eran las pruebas sueltas, sin integrarlo en el programa. Y eso he hecho... parcialmente. El botón Guardar Como... ya funciona y me permite guardar el mapa seleccionado en cualquiera de los tres formatos soportados (TMF, TPR y TMG, siglas de TileMap File, TileMap Project y TileMap Graph), creo... no he probado los TPR ni los TMG, ahora que lo pienso, pero es código reciclado, y no debería fallar, pese a varios bugs que he resuelto.

Bueno, el caso es que poco a poco la cosa avanza. Quiero terminar las funciones de guardado antes de ponerme con las de cerrar, porque si el mapa ha sido modificado, tras la ventana de aviso debería activarse la función de Guardar o Guardar Como según si ya se había guardado anteriormente o no. Con eso, las funciones del menú File (o Archivo, si hablamos en español) estarán terminadas y empezaré con las herramientas básicas del menú Edición, que tendré que conjugar con las de Mapa (añadir y quitar filas, columnas y capas son funciones más prioritarias incluso que la de relleno o selección).
Hala, como con 1001 procesos sólo va a 9 FPS, vamos a meterle 32 veces más, a ver si revienta.
(Drumpi epic moment)

Drumpi

Bueno, he hecho un nuevo avance significativo.
La opción de cerrar un mapa ya es una posibilidad, e incluso te avisa si no se ha guardado previamente (no abre la ventana de guardado, pero quiero mantener las cosas simples, porque aun me queda muchísimo por hacer).
También la ventana de guardar como funciona, con aviso de sobreescritura (y como mejora respecto a la primera versión del programa, es capaz de memorizar la ruta de dónde se guardó la última vez). Y la función de guardar está casi completa, falta por implementar la parte de detectar si el fichero está comprimido o no... aunque tampoco estoy dando la posibilidad de hacerlo ^^U. El guardar, si detecta que nunca se ha guardado el mapa llama a la función guardar como.

Y estos dos últimos días me he puesto con la ventana de selección de tile, necesaria para la mitad de las funciones de edición. Es raro que, con lo grande que es ya el programa, y con lo que me ralentizo buscando nombres de variables y cosas que ya he programado, esta ventana la haya escrito tan rápida y de forma tan sencilla. Me he permitido incluso el lujo de reescalar los tiles para que quepan en 32x32 pixels.

Y ya, de paso, he probado a ver si funcionan los mapas de dos capas con un viejo juego que empecé (siempre uso los mapas de este juego para probarlo casi todo: el scroll tileado, los motores de los nuevos juegos...) y va de miedo. Bueno, si mirais la captura, vereis que hay que hacerle un "retoquito" a la asignación de Zs a los procesos del scroll tileado, pero funcionar funcionan ^^U

Hala, como con 1001 procesos sólo va a 9 FPS, vamos a meterle 32 veces más, a ver si revienta.
(Drumpi epic moment)

SplinterGU

Download Lastest BennuGD Release: http://www.bennugd.org/node/2

FreeYourMind


Drumpi

Lo siento, pero esta vez no hay foto.
He estado una semana visitando mis parientes en Cartagena, y el ordenador lo he tocado porque tenía que sacar el cargador del móvil de la maleta :D

A pesar de eso, la ventana de selección de tile, y la ventana de selección de botón del ratón (recordemos que ponemos asignar las herramientas a cualquiera de los tres botones) ya son una realidad. He cambiado la selección de botón añadiendo botones a la ventana, he creido que era más fácil de entender que como se hacía antes, que detectaba qué botón se pulsaba de forma automática.

Con ambas cosas, ya sólo quedaba enviar esa información a la herramienta de edición... pero claro, también había que crear de forma interna una serie de funciones que crearan, almacenaran y borrasen los procesos que hacen las veces de dichas herramientas. Suena complejo, pero no lo es tanto (añade más complejidad al editor, que ya lo es de por sí, pero mantengo las cosas modulares).
Hecho lo cual... ¡YA TENGO HERRAMIENTAS DE EDICIÓN! De momento he hecho las herramientas para poner tile, otra para poner tiles mientras se mantenga el botón pulsado, y la de borrar (que es la misma que la anterior, pero con el tile nº 0 y otro icono). Ya puedo editar mapas y guardarlos, aunque sólo puedo afectar a la primera capa de los mapas (la selección de la capa de edición está aun pendiente).

Mis siguientes pasos son:
- Trabajar con la lista de acceso rápido a los tiles recientes: como en la versión anterior, en la parte de abajo se almacena una lista con los últimos tiles que se han ido seleccionando, para que al pulsar el correspondiente botón numérico de la parte superior del teclado, este se pueda asignar a cualquiera de las herramientas que tenemos asignadas a los botones del ratón, así no hay que abrir y buscar el tile que necesitamos cada poco tiempo. Aun no sé si emplear el mismo algoritmo, de borrar el que más tiempo hace que no se ha usado, o uno nuevo que borre el que menos veces se ha seleccionado (aunque eso significa que debo guardar un valor por cada tile que se use, y por cada mapa abierto :S)
- Actualizar los FPG de los tiles seleccionados: si se cambia de mapa, se cambia de FPG con los tiles que se van a usar. En las herramientas del ratón, la línea inferior tiene un clon del tile que está asignado, por lo que si se cambia de mapa y FPG, los cambios no se reflejan. Tengo que modificarlos "manualmente".
- Terminar con las herramientas disponibles en la versión 1 (mover cámara, rellenar, desplazar mapa...) y añadir las herramientas de modificación de mapa (añadir/quitar fila, columna y capa)
- Deshacer: es una herramienta que se quedó pendiente en la versión 1, y por la que su falta me ha hecho perder unas pocas horas de trabajo, al usar la herramienta de relleno donde no tocaba. Aun le estoy dando vueltas si debo incluirlo en la información de los mapas, o si debo crear una lista aparte. La segunda es la más fácil de implementar, pero es otro módulo que hay que tener en cuenta a la hora crear/cerrar mapas. Tampoco sé sí implementarla en un botón de la interfaz, o si usarla con un acceso rápido de teclado (¿backspace o ctrl+z?).

Bueno, me voy a comer, que ya es la hora.
Hala, como con 1001 procesos sólo va a 9 FPS, vamos a meterle 32 veces más, a ver si revienta.
(Drumpi epic moment)

Drumpi

Bueno, a pesar del tiempo que pueda parecer que ha pasado, apenas le he dedicado tres tardes más al proyecto. Debería seguir escribiendo código, pero me encuentro en uno de esos puntos en el que debo pasar a una nueva tarea, y esta es gorda, y como no lo tenía planificado, toca parar a pensar antes de seguir (y suele pasar de "pausa" a "hasta mañana o cuando pueda retomarlo" ^^U). ¡La planificación es importante, chicos! :D

Lo bueno es que el tiempo ha cundido. Para empezar he resuelto un bug que tenía con la herramienta de poner tiles, que daba un crash que no se había detectado hasta entonces. Lo que pasaba es que la función de cambiar tile en el mapa de tiles venía de un fichero que estaba reciclando de la versión 1 del programa. Creía que lo había adaptado, pero resulta que no, que seguía en "modo Fenix", y como el editor de tiles actual sólo edita los mapas internamente en tipo de dato WORD, en cuanto cargaba un mapa de tipo BYTE o INT el put escribía en una dirección de memoria no inicializada y ¡catapún! ventanazo de Windows. Total, que he cogido el fichero, lo he re-identado, limpiado y readaptado (casi 500 líneas) y ya funciona bien (y tengo listas para usar las funciones que añaden una fila, columna o capa al final del mapa).

Otra de las cosas que he hecho ha sido lo de actualizar los tiles seleccionados para las herramientas de edición cuando se cambiaba de mapa. No ha sido tan traumático como pensaba, y me ha sido útil para lo siguiente.

El acceso rápido a los tiles seleccionados recientemente ya es un hecho. Sí, los que aparecen en la parte inferior. Además de añadirse los tiles (usando un algoritmo de "sustituye al que más tiempo lleve sin seleccionarse") y actualizarse al cambiar de mapa seleccionado, se pueden modificar manualmente al hacer clic sobre ellos. También se ha hecho que al pulsar los botones numéricos, aparezca una ventana para seleccionar a qué botón del ratón se lo queremos asignar, pero a diferencia de la primera versión, en esta ocasión primero comprueba si hay alguna herramienta seleccionada que use tiles: si no los hay, cancela la operación de forma automática, si sólo hay una, la asigna de forma inmediata, y sólo pregunta si hay más de una herramienta. Podeis verlo en la foto adjunta.

De paso, he hecho la herramienta de desplazamiento de la cámara con ratón. Es un efecto curioso que, cuando la asignas a dos botones y usas ambos a la vez, el scroll va más rápido :D Lo dejo como una feature.
Lo que ya no sé es si el sistema que tengo para asignar estas herramientas es eficiente o no, ya que debe pasar por unas 5 capas antes de poder ser usadas: al hacer clic al botón, se activa el gestor de eventos, este llama a una función que se encarga de recabar datos llamando a diversas ventanas (selección de botón del ratón, selección de tile...), con esos datos se llama a una función de asignación de herramientas a los botones que es la que pone los iconos en la zona inferior derecha de la interfaz, y la que invoca al proceso que es la herramienta en sí, y almacena su ID en la struct del ratón.
Son muchas capas, pero mantiene el gestor de eventos sencillo, separa más o menos la capa de interfaz de la lógica, y mantiene las funciones del ratón aisladas del resto de componentes.

Ahora debo centrarme en la herramienta de relleno, que no sé si usar el mismo algoritmo recursivo de la versión 1 (por cada tile, generar tres procesos que comprueben los tiles adyacentes, salvo desde el que se invocó) o buscar un algoritmo más eficiente. Desde luego, con todo lo lenta que era la v1, el rellenado se efectuaba veloz como el rayo, más que la carga (eso si que era un algoritmo pesado de narices). Y por eso estoy en "pausa".
Aun le estoy dando vueltas a la herramienta de deshacer. Más o menos tengo claro que usaré una nueva lista, que constará de "pasos" y "elementos" (cada paso es un cambio de tile, salvo para la herramienta de relleno, que usa un "paso" con un "elemento" por cada tile que se cambie, así se puede ir deshaciendo paso a paso el "dibujar tiles continuos", pero todo el rellenado de golpe). Lo que no me queda claro es cómo activar la función "deshacer", si mediante un botón en la interfaz, mediante la tecla Z o con la combinación ctrl+Z.

Cualquier sugerencia es bienvenida.



PD: Ya queda poco para lanzar una beta, con esas dos cosas, un par de herramientas más, y la asignación de Z a los tiles, estaré en el mismo punto o casi que en el Tilemap Editor v1.
Hala, como con 1001 procesos sólo va a 9 FPS, vamos a meterle 32 veces más, a ver si revienta.
(Drumpi epic moment)

Drumpi

Antes lo digo, antes me estalla en la cara.
He implementado el código más básico de relleno (un algoritmo recursivo que se expande en las 4 direcciones, salvo de la que viene), que era el que usaba en la versión 1 y, al principio ha funcionado bien, lo hace bastante rápido y sin fallos.
Pero en cuanto he intentado rellenar un mapa de 1000x1000 (y luego uno de 400x400) para probar la velocidad, me ha salido la temida ventanita de error de Windows. Gracias a M$, he tenido que estar media hora buscando el código de error, para averiguar lo que ya sabía, y es que he tenido un fallo de desbordamiento de pila. Vamos, que me ha petado por falta de memoria (ahora es cuando teneis que ir al final y leer la frase de mi firma).

O sea, que tengo que prescindir del algoritmo sencillo y buscar otro. Ya estoy viendo cómo funciona el de rellenado por líneas (en cuanto traduzca el código, lo entenderé, porque no hay nadie que lo explique bien :S), y pensando en otros algoritmos alternativos usando un mapa de máscara y comprobaciones a base de barridos diagonales:
repetir mientras haya cambios en el mapa
   por cada fila
      por cada columna
         si el tile está marcado para cambio, comprobar los 4 adyacentes
      end
   end
end


No tengo claro cuántas pasadas serán necesarias, ni si tendría que hacer las pasadas cambiando la dirección cada vez, y lo más importante, si este algoritmo es más o menos eficiente que el de líneas (por número de instrucciones a ejecutar, iteraciones, y no usar una lista dinámica) porque creo que por memoria no será (usaría un mapa con el mismo ancho y alto que el original con datos tipo byte, porque usar tipo bit sería añadir más instrucciones para buscar el bit concreto).
La verdad es que el algoritmo me gusta, quizás lo implemente sólo por diversión y luego trate de probar con otros... aunque me conozco y diré "si funciona, así se queda... y así tiene un toque mío".

En fin, mañana veremos.
Hala, como con 1001 procesos sólo va a 9 FPS, vamos a meterle 32 veces más, a ver si revienta.
(Drumpi epic moment)

Drumpi

Bueno, dicho y hecho. Aunque ha costado bastante más trabajo del deseado (pero menos del que me esperaba), he conseguido implementar el algoritmo con éxito ¿Y sabeis qué? Funciona de miedo.
A ver, que no es el algoritmo más eficiente del mundo, y que hace unas cuantas comprobaciones de más, y cuando hay que rellenar un "pasillo" que va de suroeste a noreste o viceversa es lento, pero he conseguido que rellene un mapa de 1000x1000 tiles, con algunos espacios intercalados, en menos de un cuarto de segundo (es casi inmediato, no podría dar un tiempo ni siquiera aproximado de lo poco que hay).
Pero mira, a pesar de crear casi una copia del mapa (para dicho mapa de tiles, he necesitado 1000x1000 bytes de memoria, es decir 1MB) porque no puedo crear un array de bits sin complicar la lógica, y de que hace algunas comprobaciones de más, en condiciones favorables es más rápido y consume menos espacio en memoria que el relleno por líneas (es decir, en caso de tener pasillos diagonales noroeste-sureste, y pintar más de la mitad del mapa), pero dudo mucho que se den dichas condiciones, y no tengo la cabeza para ponerme a hacer matemáticas estadísticas :D :D :D Podría haber añadido un bucle más para que compruebe las diagonales conflictivas y sería aun más rápido, pero no quiero complicar demasiado el código y no merece la pena.

En fin, que ando en plan loco porque estoy con la cabeza a punto de reventar de tanto cálculo y debug (ha sido una sesión corta pero intensa), así que os subo el algoritmo por si teneis curiosidad. Espero que esté lo suficientemente límpio y explicado como para entenderlo. No, no se puede usar fuera del editor de mapas de tiles (a menos que cambieis obtener_tile y modificar_tile por funciones GET y PUT para mapas), es sólo para que veais el concepto.
Y sí, le he añadido condiciones de uso. Dudo que el algoritmo valga la pena, pero con cosas más tontas la gente ha hecho fortuna, así que lo pongo por si acaso (en resumen, podeis usarlo mientras no hagais dinero con él y me mencioneis en algún lado :P).

¡¡Necesito dormir!!
Hala, como con 1001 procesos sólo va a 9 FPS, vamos a meterle 32 veces más, a ver si revienta.
(Drumpi epic moment)

gecko

felicitaciones!

Incomparable la sensación de tildar como hecha una tarea difícil de la lista de pendientes
Torres Baldi Studio
http://torresbaldi.com

Ulthar Kaufman

En cuanto tenga un hueco lo pruebo, que le tengo ganas. Tiene muy buena pinta!!!

Drumpi

Ulthar, espero que te refieras al algoritmo y no al programa, porque al editor aun le falta unos cuantos días de trabajo para sacar una primera beta :D :D :D

Y hablando de días de trabajo, llevo dos jornadas de programación críticas. Se supone que en el foro soy uno de los veteranos y debo daros consejos, bueno, pues aquí van los dos consejos de la semana:
- Planificad vuestro código antes de empezar a escribir.
- Seguid a rajatabla el plan de programación.
¿Y por qué digo esto? pues porque yo no los he seguido y por eso me ha pasado lo que os voy a contar. ¡Vaya veterano estoy hecho! :D

Resuelto el problema de la herramienta de relleno (o al menos, implementada con un mínimo de calidad :P ), he pasado a la siguiente tarea, que era la de implementar los botones de zoom. En realidad, el zoom estaba planificado, y estaba prevista su implementación el primer día que se añadió el scroll tileado al motor, hace ya... pfffffff. ¿Qué pasó? Pues que me apetecía darle caña a otras partes del código más interesantes, como la lista de mapas, las herramientas de fichero o las de edición, y lo fuí dejando...
Hoy me he encontrado con que el zoom debía formar parte de más de una herramienta porque es algo asociado a las variables globales del sistema (o sea, que el zoom es común a todos los mapas, y hay que tenerlo en cuenta a la hora de abrir un mapa, crearlo, o editarlo). Así que hoy me he visto cambiando el motor de scroll tileado para que soporte el zoom, y buscando todas las referencias a la estructura TScroll.

Por fortuna, los cambios no afectan a nada más allá que a lo que hace referencia al ancho o alto de tile, he preferido no cambiar la resolución del movimiento de la cámara para no liarla más (y de paso tener un scroll suave, ya que no va a haber ningún elemento interno dentro del scroll tileado que haga uso de su posición). Vamos, que lo que más problemas ha traido han sido precisamente las herramientas de edición (poner tile, poner tile continuo, borrar tile y la herramienta de relleno), que tenía que reescalar el tile de vista previa y la referencia a la posición en la que se encuentra respecto al scroll.

Pero bueno, parece que la cosa funciona muy bien (salvo un pequeño glitch en el primer frame después del cambio, que se desplaza el mapa y aun no sé por qué). De hecho, podeis ver el efecto de usar el zoom en la imágen que adjunto ¿Recordais que dije que usaba los mapas del Echo y el FenixLand como base para probar todo? Pues ahí teneis una vista global de parte del nivel 3 del Echo, para aquellos avezados que hayan sido capaces de llegar tan lejos.

En mis siguientes pasos, antes de que se me olvide nada más, será:
- Ordenar la z de los mapas... es decir, asignarles una z a cada scroll tileado, porque de momento todos los tiles se dibujan con Z = 0 (salvo las capas traseras, que se dibujan con z = capa * 2). Es un poco molesto depurar con el panel lateral de edición por detrás de los mapas abiertos :D
- Cambiar el icono del puntero que indica qué tile está asignado a la herramienta del botón izquierdo, porque no se actualiza al cambiar de mapa seleccionado.
- Darle funcionalidad a los botones de desplazar el mapa.
- Ir pensando cómo implementar el cambio de Z en los mapas, la función de semitransparencia, y la herramienta del cuentagotas (que no sé si asignarlo como una herramienta más, con un botón en el área de edición, o usando shift + clic, como se hacía en DIV).
- ¡Ah! Que no se olvide, tengo que ir implementando las listas para deshacer cambios, aunque aun no sepa cómo ejecutar deshacer y rehacer.

Hala, como con 1001 procesos sólo va a 9 FPS, vamos a meterle 32 veces más, a ver si revienta.
(Drumpi epic moment)

Ulthar Kaufman

Quote from: Drumpi on May 14, 2016, 06:12:26 PM
Ulthar, espero que te refieras al algoritmo y no al programa, porque al editor aun le falta unos cuantos días de trabajo para sacar una primera beta :D :D :D

Ya, ya me di cuenta :D

Sigo diciendo lo mismo, tiene pintaza espectacular.

Drumpi

#27
Es increible que cosas tan sencillas se acaben complicando tanto, y que cosas realmente complicadas se simplifiquen en poquísimo código.
Quiero decir que, cuando quise implementar algo tan sencillo como "modifica el tile (x,y) por el valor n", tuve que crear una ventana de selección de botón, un sistema de almacenamiento de la función en algún botón del ratón, un sistema para ejecutar, controlar y eliminar el proceso de la función, y añadir un evento al controlador de los mismos (y al botón que lo invoca) para poner en marcha todo un proceso que trabaja en 5 niveles diferentes del editor.
Y hoy, en el segundo día, he conseguido implementar todo un sistema que permite deshacer y rehacer tantos cambios como se quiera en un mapa del tamaño del desierto del Scret of Evermore.

Al final he optado por crear la lista de elementos (ya sabeis, deshacer divide la lista en pasos, que es lo que se modifica en un clic, y en elementos, que son todos los tiles que se modifican a la vez con ese clic) usando nodos enlazados de forma simple, y añadir a los pasos un puntero extra que apunta en todo momento al último elemento de la lista. No es lo más eficiente en memoria, pero sí en velocidad y estabilidad para el sistema, que es lo que más me interesaba.
Lo he estado testeando con algo tan "gordo" como la herramienta de relleno, y he conseguido darle suficiente eficiencia para que sólo almacene los tiles que se cambian (ahora debo trasladarlo a otras herramientas, que no hacen dicha comprobación), y he comprobado que un mapa de 20x20 tarda como un cuarto de segundo en rellenar... porque tengo activadas las lineas de debug que me dicen, mediante "say", lo que se va almacenando en cada momento en la lista de deshacer, y eso ralentiza un montón el programa :D :D :D En cuanto vea que funciona, desactivaré las llamadas, y esto volará a velocidades supersónicas.
Os he hecho una secuencia de imágenes para que os hagais una idea del funcionamiento. No sé crear GIFs animados, así que tendreis que desplazar la página mientras parpadeais :D








De momento, para deshacer debe pulsarse la tecla backspace (borrar), y para rehacer shift_izquierdo + backspace. Más adelante implementaré los botones (que no sé dónde ponerlos) y que se pueda usar shift derecho (¿alguien usa shift derecho?).
Y ya, pues me he puesto con la tontería y he implementado las funciones que desplazan todo el mapa hacia arriba y hacia abajo siempre que haya espacio libre. Me faltan a los lados, pero son ya las dos y media de la madrugada y no son horas. Y sí, funcionan al pulsar el botón.

Lo gracioso es que en el último mensaje, todo esto eran cosas "secundarias", que quería dejar para más adelante hasta que le diera una vuelta porque era de lo más complicado de implementar, pero ya están hechas.
Así que sí, debería ponerme con el bug del icono del cursor, y ordenar de una vez las Z de los mapas (e incluso he estado pensando en una función para intercambiar posiciones de los mapas en la lista, y simplificar la asignación de Z por parte del usuario a "más arriba en la lista = más adelante en el editor", en lugar de valores a mano o de andar arrastrando botones de una posición a otra de una lista virtual).
Lo de transparentar los mapas también debería irlo pensando, pero tengo que hacerlo en conjunción con la selección de capas, porque aun no he hecho nada cn ese espacio morado de la parte derecha del editor, y aun quedan las herramientas del panel de mapas (modificar el tamaño de los mapas de tiles).
Hala, como con 1001 procesos sólo va a 9 FPS, vamos a meterle 32 veces más, a ver si revienta.
(Drumpi epic moment)

Drumpi

Este mensaje es para guardar las dos últimas imágenes del mensaje anterior LOL
Hala, como con 1001 procesos sólo va a 9 FPS, vamos a meterle 32 veces más, a ver si revienta.
(Drumpi epic moment)

Drumpi

Bueno, igual que dije ayer, es increible lo que se puede simplificar algo tan complejo.
El bug del cursor, en realidad era que me faltaba refrescarlo cuando se cambiaba de mapa, para eso tenía hecha una función, por lo que, para resolverlo, bastaba con escribir una simple línea al crear, abrir o cerrar un mapa. La cuestión era saber que ya existía dicha función y dónde escribirla, eso me llevó una media hora, y solucionarlo tres minutos.
Así que me puse manos a la obra con la ardua tarea de asignar valores a las Z de los tiles de los mapas... ¡y en eso tardé como media hora más! A la estructura de datos del scroll le añadí dos valores más: z1 y zn, que son la Z de los tiles en la capa 0, y qué incremento de Z tiene cada capa (puede ser de 1, que es lo habitual, 2 si queremos meter sprites entre capas... o negativos si queremos que las siguientes capas estén por encima). Luego bastaba con buscar la parte donde "actualizar_tscroll" creaba los tiles (gracias a include, estaba localizado en un único fichero de pocas líneas) y modificar la linea donde se asignaba la Z por una sencilla fórmula matemática.
Luego creé una función que recorría la lista de mapas y les asignaba esos valores a cada uno de ellos (y refrescaba el scroll) ¡Et violá! en tres líneas ya estaba resuellto.

Hala, voy a ponerme con la función que añade una fila al final del mapa, como ya la tenía hecha de antes de empezar, esto será cosa de otros 30 minut... espera, esta función va bien con mapas de una capa, pero no tiene en cuenta el desplazamiento de memoria que se genera entre capa y capa... y no, no se puede adaptar. Total, que tengo una función que debo reescribir, intentando hacer la menor cantidad de operaciones posibles.
(Ahora es cuando me pongo a pensar en voz alta para aclararme las ideas; podeis saltaros el párrafo) El problema está en que el mapa de tiles no se almacena en un array bidimensional, sino en uno unidimensional (un alloc a un puntero, con tantas casillas como tiles tiene el mapa). Sabiendo el número de filas y columnas que tiene el mapa se puede hacer una conversión sencilla. Es como guardar los datos de un tabla en un fichero, o cómo almacena los datos un ordenador en la RAM: array[(Y *ncolumnas) + X]
Ahora lo que tengo que hacer es:
array[(Y' * ncolumnas) + X'] = array[(Y * ncolumnas) + X]
Lo siento, la notación científica es la mejor forma que tengo de explicarlo. Ahora tengo que buscar la forma de hacer esa operación con todo el mapa, usando la menor cantidad de operaciones posibles, y evitar a toda costa divisiones y módulos (he comprobado que un if y una resta consumen menos tiempo que una división). Todo sin borrar información de una posición que aun no se haya evaluado.

En fin, creo que se me han aclarado algunas ideas, pero mañana necesitaré papel y lápiz para tenerlo todo perfectamente claro (sí, en programación se usa papel y lápiz ¡Qué cosas! ¿no? :D).
Me voy a dormir :D :D :D
Hala, como con 1001 procesos sólo va a 9 FPS, vamos a meterle 32 veces más, a ver si revienta.
(Drumpi epic moment)