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

Hola a todos:

Abro este hilo para mostrar mis avances con Tilemap Editor 2, un editor de mapas tileados que desarrollé hace años, y que finalmente me he puesto a crear casi de cero para arreglar los numerosos bugs y problemas de rendimiento que tenía en su primera versión.

Aquí voy a poner un enlace a la última versión que suba, pero podeis verla en su contexto a lo largo del hilo.
Ultima beta de Tilemap Editor 2
Versión Linux

A continuación os dejo con... mi yo de hace unos meses, iniciando el hilo. Yo me vuelvo al futuro a seguir desarrollando.

========================================================================================================
Como sabeis, soy el "pesao" del motor de scroll tileado, y es que a día de hoy es el protagonista del 80% de mis creaciones. Cuando no es un plataformas, me sirve para crear objetos en un modo7, o para diseñar niveles. Así que para mi, una buena herramienta para editar mapas de tiles es fundamental.
Hay varios por internet, desde luego, pero usan formatos propietarios, o hacen cosas como comprimir la información o incrustar las imágenes en el fichero, y en formato BMP. También se dijo que había cierto IDE que tendría su propio generador de mapas, con generador de código para la carga y descarga de los ficheros generados, pero no hay nada a día de hoy.

Así que me he puesto a hacer el mío propio. Hace ya muchos años, unos 10 más o menos, creé uno en Fenix que... digamos que o me tiraba meses de debug, o trabajaba con uno de los programas más lentos y exigentes en recursos que recuerdo desde la salida del "Crysis".
Ahora estoy trabajando en BennuGD, con mucha más experiencia encima, habiendo conocido varias librerías y diferentes lenguajes, por lo que el lenguaje está bastante más ordenado.

La idea es la misma de entonces: un editor que me permita editar varios mapas de tiles al mismo tiempo, usando de forma nativa el formato que creé hace ya tanto tiempo, y la última evolución de aquel motor que tan buenos resultados ha dado en varios juegos de Wiz (y si llegase a sacar aquel motor en el que estuve trabajando, un híbrido entre pintado a mapa y scroll de bennuGD, pues probar su mejora de rendimiento).

De momento el programa está en pañales. Apenas es capaz de abrir y guardar mapas, y de crear la interfaz con dos o tres funciones básicas. Las principales diferencias con la primera versión, es que ahora hay una lista con las capas disponibles en el mapa, y que para cambiar los paneles laterales se usan unos botones colocados justo encima de estos (así no hay que andar arrastrando el ratón a todo lo ancho de la pantalla). Internamente usa también un sistema propio para generar el IDE (no, no lo voy a liberar, porque tampoco lo diseñé tan a conciencia). Y también estará disponible en varios idiomas, ya que con la "clase" que diseñé de "listas de strings", crear un idioma nuevo es tan sencillo como cargar un fichero de texto u otro.
Os pongo una captura para que lo veais. No sabía si abrir el hilo, sobre todo porque gafo el proyecto, pero el foro anda tan desangelado, que por darle algo de vidilla...

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

¡Qué cosas pasan! Estoy intentando que se cree un nuevo mapa, y una de las cosas que había dejado para el final era añadir el motor de scroll tileado, para que se muestren los tiles y todo eso (me había centrado en abrir el fichero y cargar el mapa, y las opciones de cerrar y descargar).
Pues resulta que iba a añadirle la opción de zoom, una modificación que hice para el anterior programa, y leyendo el código veo que genero tres variables locales (X2 e Y2, que son las coordenadas dentro del scroll, y un INT ptr_sig, que se suponía que es un puntero al siguiente ID de proceso Tile), y pensando cómo eliminarla se me ha ocurrido un método para aplicar algo que me dijo Splinter hace mucho tiempo: evitar que el proceso de control acceda a las variables locales de los procesos tile (porque decía que según algunas pruebas el acceso a este tipo de variables era el ¿doble? de lento que el de otros tipos.

Total, que estoy reescribiendo el motor de otra manera, a ver si así es más rápido. Concretamente, creo una lista de nodos con los valores de cada tile (posición y gráfico), el ID de un proceso Tile, y a ese tile le paso un puntero directo a ese nodo. Obviamente, los procesos tile son creados y eliminados a la vez que sus propios nodos, por lo que no debería haber conflictos.
También estoy mirando si puedo reducir cálculos en el cambio de tile, que es donde se me cae el rendimiento del motor. Lo mismo cnsigo que vaya el Echo más fluido :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)

Drumpi

Vale, pues he hecho lo que me proponía: eliminar la variable local y, de paso, evitar que el proceso de control acceda a variables locales, y estos son los resultados:



No sé si es porque ahora tiene que lidiar con una lista enlazada (aunque he intentado evitar los alloc/free en todo lo posible, y recorrer los primeros nodos de la lista varias veces por frame), o que realmente la escritura en variables locales no tiene ningún impacto (al menos, en este caso), pero el nuevo motor de scroll tileado se ha mostrado ligeramente por debajo del anterior motor.
La prueba realizada ha sido hacer que el scroll se mueva solo, con un set_fps(0,0), y usar un fichero .bat para ejecutar ambos DCBs de forma simultánea con la misma versión de BennuGD. Luego intentar sincronizar ambas ventanas de forma visual (al intentar arrastrar una ventana, esta se pausa) y luego esperar a ver qué scroll recorre más distancia con el tiempo (los FPS en pantalla son simplemente orientativos).

O sea, que he perdido el tiempo ^^U
No me hace ninguna gracia tener una variable local que sólo va a usar un único proceso, y no sé si hacer la prueba con una variable pública, pero el rendimiento es importante en este proyecto (no creo que tenga los problemas de la versión 1, pero ya no me fio ni un pelo). Desde luego, este nuevo motor es más elegante algoritmicamente hablando, pero no puedo usarlo en Wiz si voy a perder 1fps.

Aun estoy en caliente, y no tengo las ideas muy claras, así que intentaré decidir mañana, pero estoy abierto a sugerencias.
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)

JaViS

jaja, bueno, al menos compartiste la informacion con el foro, y todos aprendimos algo
Working on Anarkade. A couch multiplayer 2D shooter.

SplinterGU

Quote from: Drumpi on March 07, 2016, 08:24:27 PM
Vale, pues he hecho lo que me proponía: eliminar la variable local y, de paso, evitar que el proceso de control acceda a variables locales, y estos son los resultados:



No sé si es porque ahora tiene que lidiar con una lista enlazada (aunque he intentado evitar los alloc/free en todo lo posible, y recorrer los primeros nodos de la lista varias veces por frame), o que realmente la escritura en variables locales no tiene ningún impacto (al menos, en este caso), pero el nuevo motor de scroll tileado se ha mostrado ligeramente por debajo del anterior motor.
La prueba realizada ha sido hacer que el scroll se mueva solo, con un set_fps(0,0), y usar un fichero .bat para ejecutar ambos DCBs de forma simultánea con la misma versión de BennuGD. Luego intentar sincronizar ambas ventanas de forma visual (al intentar arrastrar una ventana, esta se pausa) y luego esperar a ver qué scroll recorre más distancia con el tiempo (los FPS en pantalla son simplemente orientativos).

O sea, que he perdido el tiempo ^^U
No me hace ninguna gracia tener una variable local que sólo va a usar un único proceso, y no sé si hacer la prueba con una variable pública, pero el rendimiento es importante en este proyecto (no creo que tenga los problemas de la versión 1, pero ya no me fio ni un pelo). Desde luego, este nuevo motor es más elegante algoritmicamente hablando, pero no puedo usarlo en Wiz si voy a perder 1fps.

Aun estoy en caliente, y no tengo las ideas muy claras, así que intentaré decidir mañana, pero estoy abierto a sugerencias.

si mostraras un diff de los cambios, sin necesidad de compartir el codigo, podriamos tener una idea mas clara de que esta pasando.
Download Lastest BennuGD Release: http://www.bennugd.org/node/2

Drumpi

#5
No, os puedo subir directamente ambos códigos si quereis, de momento son de libre uso. De hecho, el motor "antiguo" ya se publicó en su día. Dadme unas horas y os pongo un paquete para que lo probeis.

EDIT: Pues ya os he hecho un paquetito. Tiene dos carpetas, una con el motor antiguo (incluye los ficheros del motor, un código de ejemplo, los recursos necesarios, y un .bat para compilarlo y ejecutarlo de forma independiente, el cual debeis modificar la primera línea para que apunte a la carpeta donde tengais guardado los binarios de Bennu), y otra con el nuevo.
Fuera de esas carpetas teneis un .bat para ejecutar ambos ejemplos a la vez (también teneis que cambiar la primera línea). Se me ha pasado añadir un WRITE al código del segundo ejemplo para poder identificar qué ventana es cuál, pero eso sabreis añadírselo ¿no? :D Siento que el código de ejemplo esté tan sucio, pero lo subía ahora o pasado mañana ^^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)

Drumpi

Bueno, mientras decidís si lo mirais o no, ya que el código está bien encapsulado, yo sigo avanzando.
He podido añadir el motor a la creación del nuevo mapa, y parece que iba bien. En realidad no lo sé porque no hay procesos tile, no puedo modificar el mapa, ni puedo moverlo, sólo sé que se crea el proceso de control del scroll y ya ^^U
Pero, la creación del scroll se hacía en las funciones que añadían nodos a la lista de mapas, y eso debía hacerse fuera. Me di cuenta al cargar mapa, cuya función pedía el nodo ya creado, así que subí un nivel la llamada a start_tscroll y... segmentation fault, o como le gusta decir a mi Windows: "El programa ha ejecutado una operación no válida y debe cerrarse". A ver si esta tarde consigo no quedarme dormido y veo en qué línea me quedé dormido al escribir el código :D :D :D
Cuando eso funcione, y pruebe la carga de mapas, ya tendré lo más básico del funcionamiento del programa: abrir, cerrar y nuevo. Faltaría guardar, pero vamos paso a paso, porque el cierre también incluye el guardar si ha habido modificaciones al mapa (y al crearse nuevo, se activa el flag de "modificado").
Luego vendría el mover el scroll tileado, y luego no sé si empezar con las herramientas de edición (para poder modificar los tiles y ver que todo funciona correctamente) o con la lista de mapas abiertos, para poder seleccionar el mapa en edición y probar el cierre de mapas de forma individual.

53 ficheros de código llevo ya :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)

SplinterGU

lo miro y te digo si se me ocurre algo.
Download Lastest BennuGD Release: http://www.bennugd.org/node/2

SplinterGU

primera sugerencia... intenta reducir el uso de funciones en las iteraciones... las funciones son casi tan costosas como los procesos, son basicamente procesos un poco mas livianos... pero se crean como un proceso, se crea una instancia, se crea un area de variables, una pila, etc... intenta usar #define en lugar de funciones donde te sea posible
Download Lastest BennuGD Release: http://www.bennugd.org/node/2

Drumpi

Mmmm, interesante. De hecho, estaba usando funciones en lugar de procesos porque precisamente se suponía que eran más rápidas de crear.
Me vendría genial para sustituir, de entrada, la función de obtener tile, que se llama tantas veces como tiles caben en pantalla (no sé cómo funcona #define, lo he estado mirando en la wiki, pero no dice si se pueden declarar variables privadas o devolver datos, aunque supongo que se le pueden pasar punteros).

Bueno, pues volviendo a lo de ayer, llevaba 3 horas buscando el fallo, y me había puesto a escribir un tochaco gordo para explicaros mi problema, porque parecía que "mágicamente" los datos del mapa de tiles habían desaparecido al salir de una función, y cuando llevaba 40 líneas y 30 minutos escribiendo, me ha venido la inspiración divina y la he resuelto (había confundido una estructura fija de datos para la interfaz, con un puntero a los datos que se estaban modificando ^^U).
He ahí la importancia de buscar ayuda externa: a veces símplemente escribiéndolo resuleves el problema :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)

SplinterGU

o puedes tambien usar funciones locales... recuerdas que hace un tiempo implemente un call a saltos a etiquetas locales? si usas eso ganaras mucha velocidad... pero no vas a tener variables ni argumentos, simplemente comparte las variables del proceso.
Download Lastest BennuGD Release: http://www.bennugd.org/node/2

SplinterGU

aca te dejo un ejemplo


import "mod_say";

global
    int a, i;

begin
    a = 1;
    say(a);

    for (i = 0; i < 10; i++)
        call inc_a;
        say(a);
    end
    return;

inc_a:
    a = a + 1 ;
    return;

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

Drumpi

#12
Vaya, lo he leido antes en el otro hilo ^^U
Sí, eso es bastante interesante, especialmente porque, en el motor antiguo, la búsqueda de tiles en el scroll, usa las mismas variables que la función.

Pero llevaba tiempo intentando escribir en Bennu al estilo C (hasta que me puse con Java, y mezclé un poco de su estilo :P ) por aquello de intentar hacerme menos dramático el salto si me tengo que poner con un lenguaje más "profesional" :D :D :D
Me miraré esto y lo de los #define y haré pruebas, a ver qué me da mejor rendimiento y se adapta más a mi estilo. Ya digo, si puedo reducir a la mitad el tiempo que tarda el motor v3.2 en refrescar la pantalla entera, el Echo iría fluido todo el tiempo y se acabarían las quejas (aunque aun tengo que terminar el anterior intento de scroll tileado, que no sé por qué falla).

EDIT: Vale, con un testeo rápido de las local routines, sustituyendo tscroll_obtener_tile por una de estas, he obtenido resultados no concluyentes. Sí, ha sido rápido, pero he comprobado que con el script que tenía para ejecutar dos programas a la vez, el segundo que ejecuto consigue un rendimiento de 10FPS más que el primero, por lo que no es una prueba muy fiable. Parece (recalco lo de parece) que cuando ejecuto la versión con rutina local la segunda, el rendimiento es ligeramente superior, entre 10 y 20 FPS, pero no puedo hacer una prueba que me de un resultado fiable, o al menos, yo no sé. La diferencia es tan pequeña que si intento ejecutarlos de forma individual, va a ser mi apreciación de las lecturas de la variable FPS la que determine cuál es más rápida, y no es un valor objetivo.
Seguiré probando cuando despeje de pestañas el notepad++ y mi cabeza ^^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)

Drumpi

Bueno, una semana después he retomado la programación del editor. No, no he podido hacer más pruebas de rendimiento de los motores de scroll porque no se me ha ocurrido ningún procedimiento que me de valores objetivos.

A pesar de mi bajo estado de forma mental, he "activado" la función de abrir mapas. Tenía previsto dedicarle toda la tarde, pero mira por donde, ¡ha funcionado a la primera! (Drumpi debe haber salido de Semana Santa de forma prematura :D ). He podido cargar el mapa de un proyecto bastante reciente, que no se ha liberado ("proyecto Placton", para más señas) y lo ha leido y mostrado perfectamente, tanto usando un "tamaño de tile" de 32x32, como el formato original de 24x24 (de la primera forma, se mantienen los tiles pero con una separación).
Tengo que seguir haciendo pruebas, a ver si me carga todos los formatos soportados, y los mapas de más de 1 capa.

Pero he aquí la buena noticia: he cargado uno de los mapas del Echo, en concreto, la del segundo nivel, la de "2012: Alien Invasion" (sí, ese nivel que tiene 22x893 tiles, y que con la anterior versión del programa iba a 1 frame cada 5 segundos) ¡Y VA SIN RALENTIZACIONES! ¡¡¡¡WIIIIIIIIIII!!!! Bueno, vale, pega algún tirón, no va 100% suave, pero eso es más por la falta de sincronización entre el intérprete y la pantalla que por falta de potencia (no, no he activado el V_Sync, ni hay planes de ello :P ).
Lo importante es que la cosa promete, y parece seguro que por fin voy a poder editar los nuevos mapas del Echo sin tener que preocuparme de que el programa vaya a paso de tortuga :)

Ahora estoy liado con la lista lateral, que indica los mapas cargados. Tengo que conseguir que se muestren, y que se puedan seleccionar, porque mi siguiente paso es activar el cierre individual de un mapa, y luego poder grabar el mapa. Con eso ya podemos empezar con las herramientas de edición (por fin).
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 le sigo dando caña. Ya tengo una lista que muestra los últimos mapas cargados. Aun no se puede desplazar, y seleccionar un mapa no tiene ningún efecto... pero al menos los botones (más bien switches) responden al ratón.

Lo que pasa es que hoy he tenido que solucionar uno de esos bugs que aparecen de pronto sin saber por qué. Me había planteado dejarlo, pero ante la posibilidad de que desaparezca, o de que al aumentar el código hacer un seguimiento del mismo se volviera imposible (y como estoy formateando unos disquetes que han aparecido en un cajón), me he puesto a buscarlo y solucionarlo.
Tras una hora y pico, me he dado cuenta que era una variable sin inicializar. Una estructura creada mediante alloc, que, supuestamente, no era necesario inicializar porque lo primero que se hace con ella es añadirle los valores iniciales (en este caso, del scroll tileado)... pero da la casualidad de que había una variable que no se inicializaba, que era precisamente la lista de procesos tile, y daba una excepción de que el proceso 256 no existía.
Ya está solucionado el tema, y he resuelto un par de pequeños bugs extra que han aparecido por el camino. Ya puedo abrir más de 20 mapas de forma simultánea sin que se me rompa el ordenador :D

Os dejo una capturita:
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)