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

Si, pero yo soy yo y no aprendo ^^U
Esta mañana se me ha ocurrido una manera interesante de meter las funciones de añadir/quitar para las filas, columnas y capas, y me he puesto a implementarlas. Añadir los botones al IDE ha sido pan comido, y que el sistema actúe ante los eventos también. La pega es implementar las funciones, porque para no repetir 3 y 3 funciones similares (3 de añadir y 3 de quitar, para filas, columnas y capas), tengo que crear una función que mueva un bloque de tiles a una nueva posición, borrando las posiciones antiguas. La pega es que, dependiendo hacia dónde se mueva el bloque, tengo que recorrerlo de arriba a abajo o al revés, o de derecha a izquierda o viceversa. Y todo eso añadiendo los cambios de tile a la lista de deshacer.
Pero una vez implementado, añadir o quitar algo básicamente es añadir una fila al final y desplazar el bloque, o desplazar el bloque y eliminar la última fila, son un par de líneas (más las necesarias para deshacer/rehacer la operación).

Resumiendo, que me quedan dos jornadas más de trabajo, más lo que se retrase por problemas técnicos o las cosas que no tengo previstas (y que van aumentando minuto a minuto en mi cabeza, acabo de darme cuenta de que el bloque se debería poder desplazar también entre capas).
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

Venga, que esto no decaiga.
Pues lo esperado, problemas por todas partes. Ayer tuve que dejar por casi imposible la función de mover el bloque de tiles, la cabeza me iba a estallar, así que me fui a dar un paseo. Esta mañana me he hecho coleguita de la consola de debug de Bennu (un poco confusa, porque te dice la siguiente linea a la que se ha ejecutado, y es difícil seguir la traza en cuanto empieza a meterse en sub-procesos :S) y entre una cosa y otra conseguí arreglarlo todo.
Luego me puse con "el par de líneas", que era algo más complejo que eso, gracias a la lista de deshacer y las múltiples capas de código (que sí, que son buenas costumbres, que aclaran el código, que ayudan a la compartimentación... pero entre capas y "plugins"... :S).
Total, que hoy por fin he conseguido añadir y quitar filas en un mapa de varias capas, y aquí teneis el resultado inicial:



Aun me queda trabajo por hacer, empezando por copiapegar estas dos funciones y usarlas para las columnas (con el peligro que eso conlleva), y crear funciones para añadir capas, que a todos los problemas tenidos hasta ahora, se suman la lista lateral de capas y la lista de datos de capas (¡esto no se acaba nunca!).
Así que mañana no sé si ponerme el casco de espartano y darle caña hasta que uno de los dos caiga, o ponerme las zapatillas de andar e ir resolviendo problemas uno a uno hasta que el ordenador diga que ya son suficientes.

Y aun me queda ordenar la lista de ficheros ¡AGHHHHHHH!
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

Puf, parece que el culebrón está llegando a su final.
¡POR FIN! Ya tengo las funciones para incluir filas, columnas y capas en cualquier parte del mapa. Como esperaba, la parte de las capas me ha costado un montón, y no sólo por la parte de llevar la lista lateral de capas y la información de las mismas. Por suerte, la lista de capas funciona a la perfección y me ha ahorrado muchísimos quebraderos de cabeza a la hora de depurar, porque ha sido mi "chivato" todo el rato para decirme si la cosa iba bien o mal. De hecho, me ha revelado varios bugs serios que iba a pasar por alto.
La fortuna ha querido que todos los fallos que he ido cometiendo estuvieran concentrados en la función de añadir o quitar capas, ya fuera al llamarla desde uno de los botones o desde las funciones de deshacer/rehacer. Y sí, es la segunda vez que hago alusión a la suerte, algo que no debería estar permitido en la programación, porque se supone que todo está calculado y medido, pero cuando has dormido pocas horas, es muy fácil cometer fallos, y nunca sabes cuando, y es un factor muy aleatorio, y aunque ha sido así, parte de la "suerte" se ha debido a que el resto del programa está muy bien construido, sobre unos cimientos sólidos y robustos... Lo siento, ya he dicho que he dormido poco y la hora no ayuda, se me va la cabeza :P

Lo cierto es que han sido dos jornadas a medio camino entre una sesión normal de trabajo y la intensidad de una Game Jam, con partes de codificación intensa, con parones para pensar el siguiente paso. Y cuando estaba cansado, atascado en un bug, buscaba cualquier valor tonto que quería ver por consola, para luego buscar el siguiente, y cuando llegase al quinto, encontrar el bug (aunque a veces me quedaba a dos pasos de encontrarlo cuando me venía una "inspiración divina" que me lo señalaba con carteles de neón).

Voy a ir cortando antes de que se me vaya la cabeza del todo. Lo dicho, las funciones para añadir filas, columnas y capas en mitad del mapa funcionan, así que me he puesto a trastear con el fichero de configuración para añadir la lista de números que indican los botones que queremos tener en la barra de herramientas. Eso significa que me puse a escribir unas 100 líneas extra para inicializar, crear, destruir y actualizar la lista de botones que van en dicha barra. Sí, otra lista enlazada, aunque por suerte en esta ocasión han sido 4 arrays dinámicos dentro de una struct global (nota: la struct es global porque no tenemos clases donde encapsular el acceso a la misma LOL). Con los botones puestos, ya sólo quedaba crear el proceso de control que ejecutase todas y cada una de las funciones de los posibles botones que van a ir ahí... y no son pocas.

La buena noticia es que gracias al gestor de eventos, parte principal del sistema, cada botón sólo necesita de una línea para dar comienzo a la ristra de órdenes que lleva asociada, y todas son iguales, salvo por una constante y un valor. Hasta ahora he implementado casi todas las funciones de fichero (abrir, nuevo, guardar...) y la mayoría de las de edición; me quedan 4 de las de mapa que tienen el icono ya hecho, pero tengo que hacer unas cuantas más que no tienen icono porque no eran funciones de por sí, como mover todos los tiles, cambiar el zoom, o modificar el tamaño del mapa (he contado unas 10).
Después de eso, espero no ponerme a ordenar ficheros. Quedaría modificar la cámara al cambiar el zoom, los textos de los botones de acciones de fichero y... tenía otra tontería por ahí apuntada, no sé ¿Mostrar las coordenadas del ratón? ¿Dónde?

Lo mismo no toco mucho más y lanzo de una vez la beta. ¿Qué número de versión debería ponerle? Si le pongo la 1.1.3, que es la que le toca parecerá una revisión del primer editor, si le pongo la 2.1.3 parecerá que ya hay una v2 finalizada, y si le pongo la 0.1.3 que es la que tengo como nombre de la carpeta (porque es un proyecto nuevo casi de cero) ni siquiera parecería que hubiera una versión previa :S

¡Una cama, por favor!
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

Ya lo tenía, estaba a punto de publicar la beta cuando Drumpi me ha hecho una de sus jugarretas y me ha tenido toda la tarde dándole vueltas al mismo fallo.
La verdad es que no puedo culparlo de algo que en realidad es error mío (pero molaba como intro del mensaje :D ). Ya había añadido los botones a la barra, con otros dos extra de zoom (voy a dejar algunas funciones sin poner como botón, porque si no ¿para qué los paneles laterales?), modificado en tiempo de ejecución los textos de los botones de guardar y salir, e incluso me había permitido el lujo de añadir un pequeño cuadro junto a los tiles de acceso rápido para mostrar la posición del ratón y el tile que había bajo él (siempre en la capa seleccionada). Aquí podeis verlo.



Pero al querer modificar la posición del scroll tras hacer zoom, para que la cámara intentase mantenerse más o menos cerca de la zona donde se estaba editando, ha saltado un error que hacía que todo el mapa apareciese desplazado hasta el siguiente refresco del mapa (esa función que se invoca cada vez que la cámara cambia su posición de un tile a otro).
Hace tiempo ya saltó el problema con la propia función de zoom. No le di importancia porque sólo se apreciaba durante un único frame, y lo achacaba a los problemas típicos del orden de ejecución, podía dejarlo para más adelante. Pero al modificar la posición de la cámara, este desplazamiento se mantenía estático hasta el refresco, y con el zoom al mínimo un tile de 16x16 necesitaba desplazar el mapa 128 pixels antes de que eso sucediera.

Me he tirado más de dos horas mirando el código sin tener el más mínimo indicio del fallo. El debuger no ayudaba porque toda la información estaba contenida en punteros, y crear funciones para escribir los datos me iba a llevar un par de días. Al final encontré el hilo del ovillo, y pude comprobar que era cosa de la función de refresco del scroll.
Hasta ahora esta función sólo podía ser llamada por el proceso de control del scroll, y en contadas excepciones, por algún elemento externo (generalmente, por cambiar un tile o el FPG). Ahora que era llamada por una función del sistema, en determinadas ocasiones se produce un efecto no deseado, y es que la cámara no modifique su posición y algunas operaciones se quedan sin realizar.

Aun no he podido determinar el alcance de los "daños". He visto que al coincidir la posición de la cámara con el frame anterior, se llamaba a la función de desplazamiento rápido de tiles con valores inaceptables, llegando a mover el mapa incluso tile y medio. He tenido que pasar los datos de la posición anterior a la estructura del scroll para que la función de refresco pudiera actualizar los valores si se hace desde fuera.
Otro de los efectos no deseados se ha dado con algunos cálculos que hasta ahora eran secundarios. Pensaba que era cosa del cálculo del tile en el que se hallaba la cámara, pero resulta que no, que he aislado el fallo a los cálculos de la posición del tile (0,0), que como digo, era información extra para el usuario... aunque he visto que se usa en algunos cálculos principales.

Tengo que ver cuales son los datos concretos que tengo que actualizar, y lo más importante: por qué. En teoría, toda modificación de la cámara del scroll tileado debería haber estado cubierta por el proceso de control, y este tenía que ser el encargado de refrescar el scroll incluso antes que cualquier llamada externa. Y sin embargo la llamada externa no responde como el proceso de control, y la omisión de esos cálculos han provocado todo el caos de hoy.
Sé que esto os dice poco o nada a vosotros, pero tengo que desahogarme e intentar analizar el problema, y ya sabeis que a veces, escribir sobre él trae la luz a las cabezas.

Como digo al principio del mensaje, el programa está casi terminado en su versión beta, y quiero dejarla lo más estable posible antes de lanzarla, para que no pase como con la primera versión. Y también quiero ir eliminando de la lista la mayor cantidad de "cosillas tontas" que se suelen dejar para el final, y que al acumularse suman varios días de desarrollo. Aun tengo pendiente mover un texto de error crítico de un SAY a una ventana (bueno, hay varios, pero este es el que más importante sería), y añadir la típica ventana de créditos, pero eso supone desarrollar el sistema de menús y submenús de la parte superior, y aunque tengo una ligera idea de por dónde lo quiero llevar, aun tengo muchos detalles que arreglar.
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

De acuerdo, voy a anotar esto antes de que se me olvide, para tenerlo registrado:

Resulta que esos cálculos que no se actualizaban, todos son necesarios de una forma u otra. Estaba usando la función ts_actualiza_tiles como si fuera la función de refresco de todo el scroll tileado, y no lo es. Sólo es una función que actualiza la posición y la lista de tiles del propio scroll. La actualización de los datos del scroll tileado la hace sólo y exclusivamente el proceso de control, porque en función de unos cálculos hace un refresco completo o un simple desplazamiento de tiles.
¿Qué pasaba? pues que al hacer zoom, efectivamente la cámara se desplazaba, pero al cambiar el tamaño de los tiles, ese desplazamiento mantenía la cámara dentro del mismo tile de antes, que es el requisito indispensable para forzar el refresco completo.

Para no crear una variable que forzase el refresco desde fuera (que podría provocar que no se viera hasta un frame después), ni modificar la función de refresco para que hiciera los cálculos del tscroll dos veces (una por el proceso de control, y otra por la llamada de la función de refresco por parte del sistema desde el propio proceso de control), lo que he hecho ha sido crear una función de refresco que prácticamente hace lo mismo que el proceso de control, incluida la llamada a ts_actualiza_tiles, y en el proceso de refresco del sistema he buscado la fuente de la llamada, y si father.reserved.process_type es el proceso de control, en lugar de llamar a esta nueva función, llama directamente a ts_actualiza_tiles... y ya después aplica toda la lógica extra de modificar el alpha de los tiles y demás.

No sé si es la solución más elegante o no. Le he dado vueltas hasta casi marearme, he empezado el planteamiento cuarenta veces, una por cada vez que se complicaba demasiado el código en mi cabeza. Y de momento las pruebas son prometedoras, ya no hay glitches, el zoom funciona (autodesplazamiento incluido) y no sé si tengo fuerzas para poner el programa al límite con varios mapas abiertos a la vez.

De momento voy a relajarme pensando si le añado un botón de "atrás" a la ventana de selección de ficheros, o selección mediante doble clic o algo sencillo, y si veo que se complica mucho la cosa, esta tarde subo la beta.
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, pues ya está. Ayer salí a que me diera el aire y no pude arreglar nada, pero por la noche le dediqué unos minutos y añadí los botones de deshacer a la barra de botones por defecto, un nuevo valor para que podais escoger el mapa para el scroll de fondo que más os guste (los valores son el número de gráfico del fichero grafs/scroll_bg.fpg, podeis añadir el que querais) y solucioné un bug que metí con la nueva función del sistema de refrescar el mapa. Si quereis personalizar la barra de botones, los valores son los gráficos contenidos en grafs/system_icons.fpg... pero no useis los de los ratones, no sirven para eso... ni la del cuentagotas, si se ha quedado ahí ^^U).

Esta mañana he estado probando la versión antes de subirla creando un nuevo nivel para "El Ballena Azul" ¡y vaya diferencia! Bueno, en realidad la versión 1 no tenía ningún problema en mover esos mapas, y por ahí había poca diferencia, pero el poder editar los dos mapas a la vez, el visible y el de durezas, ha ayudado a poder resolver en cuestión de segundos problemas que antes tardaba minutos, y esos ajustes finales han pasado de necesitar de 5 a 10 minutos, a unos ridículos 20 a 120 segundos. He tenido problemas porque el mapa de durezas usaba tiles de 32x32 y el visible de 64x64, y el zoom afecta a todos los mapas por igual.
Aparte de eso, he aprovechado para añadir la rueda del ratón a la ventana de selección de tile, que no lo había hecho (por eso hay que probar las cosas antes de subirlas.

Así que aquí os dejo la versión 0.2.0 de Tilemap Editor 2. No os preocupeis, voy a poner un enlace al fichero en el primer mensaje del hilo.
No trae instrucciones (lo siento, pero ya estoy KO con el proyecto, podeis preguntarme las dudas que tengais). Y es sólo el ejecutable para windows, pero si teneis la versión de Linux, el port es básicamente cambiar los binarios y el script de ejecución (o al revés, añadir a aquella versión el DCB y cambiar las carpetas de gráficos y textos por las nuevas).
Tampoco trae código fuente, si a alguien le interesa me lo puede pedir y se lo mando por correo (pero voy a poner como condición que esa persona haya hecho algún juego en Bennu y lo haya subido, pertenezca al Fenix, Bennu o PixTudio team, o que sea un asiduo del foro :P )
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)

FreeYourMind

yo cumplo las condiciones creo  ;D  gracias.

Drumpi

Okis, pues cuando Drumpi encuentre tu correo, intentaré mandártelo ^^U

Mientras, como no tengo sueño, he preparado un binario para Linux.
Ya sólo me falta un Notepad++ para desarrollar el Echo también en Linux :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)

Fede

Pues me ha dado por probar el TME y ...

No he sido capaz de cargar un mapa del Echo. (Si es que se puede). Vale que no me he leído el hilo, así que lo mismo es que no se puede. :D

A ver si ponemos al menos un read.me, y un ficherito de ejemplo para cargar, que soy muy vago y no tengo ganas de comerme el tarro.

Por lo demás.... muuuu friki  y al puro estilo Drumpi.

Mi enhorabuena. :)

Sugerencia:

Cuando intento abrir un tmf, ¿por qué no coge automáticamente el tamaño de este? Lo digo porque el mío si lo hace. :D

Es más, yo lo que hago es crearme un tpr (tile map project) donde tengo asociados las durezas, los gráficos y el mapa de tiles.)

Ahora bien, yo no tengo multicapas como el tuyo. :p


Freee, que no lo pongo porque está muuuuuuuu verde. Que te conozco. :D


Si quieres ser sabio, aprende a interrogar razonablemente, a escuchar con atención, a responder serenamente y a callar cuando no tengas nada que decir.

Drumpi

A ver. Los mapas del Echo sí que los carga, de hecho, los he puesto de prueba en algún screenshot:

Tienes que darle a abrir, que es el icono de la hoja de papel con la flecha azul que sale.
Busca el fichero tmf, por ejemplo, lvl3_city.tmf.
A continuación tienes que indicar el tamaño de los tiles: 16x16 (el formato TMF contiene sólo información del mapa de tiles, no de los tiles en sí, por eso debes especificar su tamaño y los gráficos que vas a usar... pero no el tamaño del mapa).
Luego buscar el FPG, en este caso, grafs/stylish/level3.fpg
Y ya está, debería cargártelo entero.

Obviamente, a la hora de trabajar es más cómodo usar un TPR, que es un fichero Tilemap PRoject, y como es un proyecto, este sí almacena los datos que necesita el programa para funcionar, y eso incluye el tamaño de tile y el fichero de gráficos (ojo, una vez seleccionado un fichero de gráficos, no se puede cambiar, ni se debe mover el FPG de sitio, aun no he añadido esa funcionalidad al editor, está pendiente). Cuando hayas terminado con el proyecto, usas "guardar como..." y ya lo almacenas como TMF.

Y ojo al dato: ahora puedes abrir el mapa visible y el de durezas a la vez. Las flechas al lado de la lista de mapas (lista verde) te sirve para ordenarlos en profundidad (cuanto más arriba, más adelante está). Y los botones de la zona morada te permiten seleccionar la transparencia de las capas si los pulsas y arrastras.

Ya sé que falta un readme, quería terminarlo ya y ponerme con el Echo, pero cualquier cosa del programa está explicada en este hilo, porque lo fui poniendo a medida que lo implementaba :D
Lo sé, no es excusa ^^U

Ojo, que muchos de mis juegos son compatibles con esta herramienta: Screen Break Time, Drajon Lol: devolución, Boulder, Plaaaa...se ha quedado muy buena noche ¿no? :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)

Fede

Gracias machote.


Y si, hace fresquito esta mañana. :)
Si quieres ser sabio, aprende a interrogar razonablemente, a escuchar con atención, a responder serenamente y a callar cuando no tengas nada que decir.