English version


Isomot v1.0 por Ignacio Pérez Gil (perezg_ret[]terra.es)

- ¿Que es Isomot?
- Notas sobre la distribución
- Cómo usar Isomot en tu proyecto Allegro
- La rejilla
- Paredes y losetas
- Objetos
- Detección de colisiones
- Coordenadas de la rejilla
- Convirtiendo coordenadas entre 2d y 3d
- Sombras
- Objetos transparentes
- Dibujando la vista isométrica
- Errores
- El fichero ism_lng.h
- Resumen de funciones
- Consejos
- Historia
- Agradecimientos


- ¿Que es Isomot?


     Isomot es un motor de gráficos isométricos para Allegro, en la más genuina tradición del Filmation (¿recuerdas juegos como Knight Lore, Alien 8, Sweevo's World, Head Over Hells, etc?) con una perspectiva 1/2,1/2,1 y donde el eje x es el que va hacia abajo y a la derecha, el y hacia abajo y a la izquierda, y el z hacia arriba. Este documento no pretende ser un tutorial sobre la perspectiva isométrica, así que supondré que tienes unos conocimientos básicos sobre la misma. De todas formas, para cualquier pregunta, me puedes escribir a perezg_ret[]terra.es. Isomot tiene un interface multilingüe; español e inglés son los lenguajes soportados actualmente (este documento solo trata el interface en español). Añadir nuevos lenguajes al interface es muy fácil, si quieres hacer el interface para algún otro lenguaje, mándame un mensaje y te diré como.


- Notas sobre la distribución

     Este código fuente es distribuido "tal cual", sin ninguna garantía, y no aceptaré ningún tipo de responsabilidad por ningún tipo de daño que pueda causar.

     Eres libre de usarlo en tus propios programas, tal cual o añadiéndole modificaciones de tu propia cosecha, siempre que no sea con motivos comerciales. Eso sí, una mención en los créditos, y un pequeño correo electrónico diciéndome para qué lo estás usando, lo que piensas de él, los cambios que le has hecho, etc. sería muy amable por tu parte :)


- Cómo usar Isomot en tu proyecto Allegro

     Para usar Isomot, sólo tienes que añadir el fichero isomot.c a tu proyecto (y no olvides el #include "isomot.h" en el fichero o ficheros en los que lo vayas a usar). Fácil, ¿verdad?


- La rejilla

     Las habitaciones de cualquier juego isométrico típico tienen una rejilla sobre la cuál casi todos los objetos están colocados. Para definir esta rejilla, debes usar la siguiente función:

int ism_establecer_rejilla(int x, int y, int anchura);
Descripción: Define (o redefine) la rejilla.
Parámetros: x, y: las dimensiones de la rejilla.
anchura: el ancho de las celdas de la rejilla.
Comentarios: El parámetro anchura debe ser mayor que 1.
Devuelve: 0 si funcionó, -1 si falló.

     Por ejemplo, para definir una rejilla como ésta:


Fig. 1: la rejilla.

   debes usar ism_establecer_rejilla(8,8,16); Si no entiendes porqué el ancho de la rejilla es 16 en este ejemplo, échale un vistazo a la siguiente ampliación de una de las losetas:


Fig. 2: loseta.

     Importante: definir la rejilla es lo primero que debes hacer al usar Isomot; cualquier otra de sus funciones a la que llames antes de definirla devolverá un error.

     Ten en cuenta que, cada vez que defines la rejilla, se borran todos los elementos (objetos, etc.) de la vista isométrica, así que usa esta función con cuidado si la usas varias veces, en lugar de una sola al principio del programa (por ejemplo, para redimensionarla).

     Al llamar a la función ism_establecer_rejilla se reserva una cierta cantidad de memoria para uso interno del motor. Así pues, cuando quieras liberar esta memoria (normalmente en el código de finalización de tu programa), deberás llamar a la siguiente función:

int ism_destruir_todo(void);
Descripción: Libera la memoria reservada por Isomot para su uso interno.
Parámetros: Ninguno.
Comentarios: Si después de llamar a esta función quieres volver a usar Isomot, tendrás que volver a llamar a ism_establecer_rejilla para que se vuelva a definir la rejilla y se vuelva a reservar la memoria necesaria.
Devuelve: 0 si funcionó, -1 si falló.


- Paredes y losetas


Fig. 3: Head Over Heels.

     En la imágen anterior, extraida del "Head Over Heels", se pueden ver claramente algunos de los más comunes elementos de las pantallas de cualquier juego isométrico: los diferentes tipos de paredes, y las losetas. Isomot dibuja las paredes como un mosáico de imágenes alineadas con el suelo. Para establecer estas imágenes y las del propio suelo, debes usar las siguientes funciones:

int ism_colocar_pared(BITMAP *mapa, unsigned char eje, int pared);
Descripción: Asigna un mapa a una o varias de las partes (alineadas con las losetas del suelo) en que se divide una pared.
Parámetros: mapa: el mapa de la pared.
eje: el eje correspondiente a la pared. Los valores posibles son SUP_X, INF_X, SUP_Y e INF_Y.
pared: el número de la pared. Puedes usar TODAS para establecer todas las paredes del eje indicado.
Devuelve: 0 si funcionó, -1 si falló.

int ism_colocar_loseta(BITMAP *mapa, int x, int y);
Descripción: Asigna un mapa a una o varias losetas del suelo.
Parámetros: mapa: el mapa de la loseta.
x, y: las coordenadas de la loseta en la rejilla. Puedes usar TODAS en una de las coordenadas para establecer toda la fila de losetas. También la puedes usar en ambas coordenadas para establecer todas las losetas a la vez.
Devuelve: 0 si funcionó, -1 si falló.

int ism_colocar_suelo(BITMAP *mapa);
Descripción: Asigna un mapa para ser utilizado al dibujar el suelo, aparte de las losetas individuales que hayas podido definir con ism_colocar_loseta.
Parámetros: mapa: el mapa a dibujar como suelo de la habitación.
Devuelve: 0 si funcionó, -1 si falló.

     Además, puedes mover las paredes, el suelo y sus losetas con las siguientes funciones:

int ism_mover_pared(unsigned char eje, int pared,int despeje, int despaltura);
Descripción: Mueve una o varias paredes.
Parámetros:
eje: el eje correspondiente a la pared. Los valores posibles son SUP_X, INF_X, SUP_Y e INF_Y.
pared: el número de la pared. Puedes usar TODAS para mover todas las paredes del eje indicado.
despeje, despaltura: desplazamiento de la pared en el sentido del eje indicado y en la altura, respectivamente.
Devuelve: 0 si funcionó, -1 si falló.

int ism_mover_loseta(int x, int y, int despx, int despy);
Descripción: Mueve una o varias losetas.
Parámetros:
x, y: las coordenadas de la loseta en la rejilla. Puedes usar TODAS en una de las coordenadas para mover toda la fila de losetas. También la puedes usar en ambas coordenadas para mover todas las losetas a la vez.
despx, despy: desplazamiento de la loseta en los ejes x e y, respectivamente.
Devuelve: 0 si funcionó, -1 si falló.

int ism_mover_suelo(int despx, int despy);
Descripción: Mueve el suelo.
Parámetros: despx, despy: desplazamiento del suelo en los ejes x e y, respectivamente.
Devuelve: 0 si funcionó, -1 si falló.


- Objetos

     Objetos son todos los elementos que van a ser dibujados dentro de la habitación, como bloques de piedra, enemigos, etc. Todo objeto colocado en la habitación está identificado por un valor del tipo de datos ism_id. Hay dos tipos de objetos: objetos de rejilla y objetos libres. Los objetos de rejilla son aquellos que están colocados en una posición concreta de la rejilla, y tienen las mismas anchuras que sus celdas. Los objetos rejilla son, básicamente, los bloques típicos del juego sobre los que el jugador va a saltar, etc. No se puede cambiar las coordenadas x e y de un objeto rejilla, solo se puede cambiar su z. Por el contrario, objetos libres son aquellos que pueden estar en cualquier lugar y moverse libremente por la habitación, como, por ejemplo, los enemigos, o el propio jugador, o todo aquello que deba tener anchuras distintas de las de las celdas de la rejilla. Para aclarar esto un poco, puedes ver la siguiente imagen:


Fig. 4: Knight Lore.

     En esta habitación del "Knight Lore" de Ultimate (por cierto, el primer juego que usó la técnica Filmation), todas las trampas de pinchos son objetos rejilla, fijos a una rejilla de 8x8 que se ha dibujado encima de la imágen, pero Sabreman (el personaje del sombrero) y el guardián (el del casco) pueden moverse por la habitación con bastante libertad, por lo que son objetos libres.

     Para colocar un objeto rejilla en la habitación, la función a utilizar es:

ism_id ism_colocar_objeto_rejilla(int x, int y, int z, int altura, BITMAP *mapa, BITMAP *sombra);
Descripción: Coloca un objeto rejilla en la vista isométrica.
Parámetros:
x, y: las coordenadas de la rejilla en las que colocar el objeto.
z: la coordenada z del objeto, referida a su base. Puedes usar ENCIMA para ponerlo sobre el objeto (de culquier tipo) colocado a más altura en esa posición, es decir, colmo si se hubiera dejado caer desde el cielo. Esto es útil para formar columnas de objetos unos encima de otros sin tener que calcular la coordenada z de cada uno.
altura: la altura del objeto.
mapa: el mapa del objeto. Si colocas este parámetro a NULL, el objeto no se dibujará, pero a todos los efectos (colisiones, etc.) seguirá existiendo.
sombra: la sombra del objeto. Si colocas este parámetro a NULL, el objeto no tendrá sombra.
Devuelve: El identificador del objeto si funcionó, ID_ERROR si falló.

     Para colocar un objeto libre en la habitación:

ism_id ism_colocar_objeto_libre(int x, int y, int z, int anchurax, int anchuray, int altura, BITMAP *mapa, BITMAP *sombra);
Descripción: Coloca un objeto libre en la vista isométrica.
Parámetros:
x, y, z: las coordenadas x, y y z del objeto, referidas al punto más a la izquierda de su base. Puedes usar ENCIMA el el parámetro z para ponerlo sobre el objeto (de culquier tipo) colocado a más altura en esa posición, es decir, colmo si se hubiera dejado caer desde el cielo. Esto es útil para formar columnas de objetos unos encima de otros sin tener que calcular la coordenada z de cada uno.
anchurax, anchuray: la anchura del objeto en las dimensiones X e Y.
altura: la altura del objeto.
mapa: el mapa del objeto. Si colocas este parámetro a NULL, el objeto no se dibujará, pero a todos los efectos (colisiones, etc.) seguirá existiendo.
sombra: la sombra del objeto. Si colocas este parámetro a NULL, el objeto no tendrá sombra.
Devuelve: El identificador del objeto si funcionó, ID_ERROR si falló.

     Para obtener un dato concreto acerca de un objeto:

int ism_obtener_dato_objeto(ism_id id, unsigned char dato);
Descripción: Devuelve el dato solicitado acerca del objeto.
Parámetros: id: el identificador del objeto.
dato: el dato que se quiere obtener acerca del objeto. Los valores posibles son: D_X (la coordenada x), D_Y (la coordenada y), D_Z (la coordenada z), D_ALTURA (altura), D_ANCHURA_X (anchura en la dimensión x), D_ANCHURA_Y (anchura en la dimensión y) y D_TRANSP (porcentaje de transparencia del objeto)
Comentarios: Si se solicita la coordenada x o la y de un objeto rejilla, la función devuelve la coordenada de la celda de la rejilla en la que se encuentra.
Devuelve: El dato solicitado si funcionó, -1 si falló.

     Hay una manera más fácil de obtener las coordenadas de un objeto que hacer tres llamadas sucesivas a la función anterior:

int ism_obtener_coords_objeto(ism_id id, int *dstx, int *dsty, int *dstz);
Descripción: Almacena las coordenadas del objeto en las variables indicadas.
Parámetros: id: el identificador del objeto.
dstx, dsty, dstz: punteros a las variables donde se quiere que la función almacene las coordenadas del objeto.
Comentarios: Si el objeto es de tipo rejilla, los valores almacenado en dstx y dsty serán los de la celda correspondiente de la rejilla.
Devuelve: 0 si funcionó, -1 si falló.

     Para modificar una característica concreta de un objeto, usa la función:

int ism_cambiar_dato_objeto(ism_id id, unsigned char dato, int valor, unsigned char modo);
Descripción: Modifica el dato solicitado del objeto.
Parámetros: id: el identificador del objeto.
dato: el dato que quieres modificar. Los valores posibles son: D_X (la coordenada x), D_Y (la coordenada y), D_Z (la coordenada z), D_ALTURA (altura), D_ANCHURA_X (anchura en la dimensión X), D_ANCHURA_Y (anchura en la dimensión Y) y D_TRANSP (porcentaje de transparencia del objeto)
valor: el nuevo valor del dato.
modo: el modo en el que quieres cambiar el dato. Puedes usar CAMBIAR para sustituir el dato antiguo por el nuevo, o SUMAR para sumarlo.
Comentarios: Ocurrirá un error si tratas de cambiar la coordenada X o Y de un objeto rejilla, alguna de sus anchuras, o su porcentaje de transparencia.
Devuelve: 0 si funcionó, -1 si falló.

     Y para cambiar rápida y fácilmente las coordenadas de un objeto libre, solo tienes que usar:

int ism_mover_objeto(ism_id id, int x, int y, int z, unsigned char modo);
Descripción: Modifica las coordenadas del objeto indicado.
Parámetros: id: el identificador del objeto.
x, y, z: las nuevas coordenadas a las que hay que mover el objeto.
modo: el modo en que se quiere interpretar las nuevas coordenadas. Puedes usar CAMBIAR para cambiar las coordenadas del objeto por las x, y y z indicadas en la función, o SUMAR para sumarlas.
Comentarios: Ocurrirá un error si tratas de mover un objeto rejilla con esta función.
Devuelve: 0 si funcionó, -1 si falló.

     Para cambiar el mapa de un objeto:

int ism_cambiar_mapa_objeto(ism_id id, BITMAP *mapa);
Descripción: Cambia la imágen del objeto.
Parámetros: id: el identificador del objeto.
mapa: el mapa con la nueva imágen del objeto.
Devuelve: 0 si funcionó, -1 si falló.

     Para cambiar la sombra de un objeto:

int ism_cambiar_sombra_objeto(ism_id id, BITMAP *sombra);
Descripción: Cambia la sombra de un objeto.
Parámetros: id: el identificador del objeto.
sombra: el mapa con la nueva sombra del objeto.
Devuelve: 0 si funcionó, -1 si falló.

     La función para eliminar un objeto es:

int ism_quitar_objeto(ism_id id);
Descripción: Borra el objeto indicado de la vista isométrica.
Parámetros: id: el identificador del objeto.
Devuelve: 0 si funcionó, -1 si falló.

     Para saber si un objeto determinado existe:

int ism_existe_objeto(ism_id id);
Descripción: Indica si el existe el objeto con el identificador indicado.
Parámetros: id: el identificador del objeto.
Devuelve: 1 si el objeto existe, 0 en otro caso.

     Finalmente, para quitar todos los objetos, paredes y losetas:

int ism_vaciar_mundo_isom(void);
Descripción: Vacía por completo la vista isométrica.
Parámetros: Ninguno.
Devuelve: 0 si funcionó, -1 si falló.


- Detección de colisiones

     Si, al intentar mover un objeto, este choca con otro, con alguna pared o con el suelo, la función utilizada para ello devolverá un error, y el movimiento no se llevará a cabo. Además de esto, los identificadores de todos los objetos paredes, etc. con que haya chocado se almacenan en una pila interna del motor. Para consultar esta pila y comprobar con qué elementos ha colisionado el objeto al intentar moverlo, puedes usar llamadas sucesivas a la siguiente función:

int ism_extraer_id_blq(void);
Descripción: Extráe un identificador de la pila de colisiones.
Parámetros: Ninguno.
Devuelve: NO_ID si no ha chocado con nada, o si ya se han extraido todos los identificadores de la pila de colisiones en llamadas anteriores a esta función, el identificador de un objeto con el que el objeto que se ha intentado mover haya chocado, o ID_PARED_SUP_X, ID_PARED_SUP_Y, ID_PARED_INF_X, ID_PARED_INF_Y o ID_SUELO si ha chocado con alguna pared o con el suelo.

     Si quieres saber si el último objeto movido ha colisionado con un determinado objeto, pared o con el suelo:

int ism_colisionado_con(ism_id id);
Descripción: Comprueba si el último objeto movido ha colisionado con el suelo, pared u objeto indicado.
Parámetros: id: el identificador del objeto con el que se quiere saber si se ha chocado, o ID_PARED_SUP_X, ID_PARED_SUP_Y, ID_PARED_INF_X, ID_PARED_INF_Y o ID_SUELO si se quiere saber si se ha chocado con alguna pared o con el suelo.
Devuelve: 1 si se ha chocado con el objeto, suelo o pared indicada, 0 en otro caso.

     Si quieres saber con cuantos objetos ha chocado el último objeto movido, incluyendo paredes y suelo:

int ism_num_colisiones(void);
Descripción: Devuelve el número de objetos, paredes y suelo con los que ha colisionado el último objeto movido.
Parámetros: Ninguno.
Devuelve: El número de objetos, paredes y suelo con los que ha colisionado el último objeto movido.


- Coordenadas de la rejilla

     Al usar las funciones del motor para averiguar las coordenadas de un objeto rejilla, lo que obtenemos para la x y la y no son sus coordenadas reales basadas en los ejes de referencia, lo que llamaremos "coordenadas libres", sino las referidas a su situación dentro de la rejilla, que llamaremos "coordenadas de rejilla". Normalmente, con esto debe ser más que suficiente para nuestros propósitos, pero puede haber ocasiones en que nos interese transformar coordenadas de un formato a otro, para comparar las posiciones de un objeto rejilla y otro libre, o para calcular su distancia, por ejemplo. Para ello, disponemos de las siguintes dos funciones:

int ism_obtener_coords_libres(int x, int y, int *xl, int *yl);
Descripción: Obtiene las coordenadas x e y, respecto de los ejes de coordenadas, del punto situado más a la izquierda de una celda dada de la rejilla.
Parámetros: x, y: coordenadas de rejilla de la celda.
xl, yl: punteros a las variables donde se quiere almacenar las x e y libres.
Devuelve: 0 si funcionó, -1 si falló.

int ism_obtener_coords_celda(int x, int y, int *xc, int *yc);
Descripción: Obtiene las coordenadas de rejilla de la celda del suelo sobre la que se encuentra un punto determinado.
Parámetros: x, y: coordenadas x e y libres del punto dado.
xc, yc: punteros a las variables donde se quiere almacenar las x e y de rejilla.
Devuelve: 0 si funcionó, -1 si falló.


- Convirtiendo coordenadas entre 2d y 3d

     Cuando uses Isomot, por lo general manejarás dos tipos de coordenadas; las 2d referidas a las imágenes, y las 3d de tu mundo isométrico. Algunas veces, te puede resultar útil transformar coordenadas de un tipo en otro (por ejemplo, para usar el ratón). Para ello, puedes utilizar las dos funciones siguientes:

int ism_coords_iso_a_2d(int xiso, int yiso, int ziso, int *x2d, int *y2d);
Descripción: Transforma coordenadas isométricas 3d en sus equivalentes 2d. Es decir, indica en que punto de la imágen de destino se dibujará un punto isométrico determinado.
Parámetros: xiso, yiso, ziso: las coordenadas isométricas que quieres transformar en 2d.
x2d, y2d: punteros a las variables donde quieres que se almacenen los valores x e y 2d.
Comentarios: Las coordenadas 2d devueltas se refieren al mapa donde estés dibujando el mundo isométrico y al lugar del mismo en el que esté dibujando el origen de coordenadas isométrico, es decir, los valores de tu última llamada a ism_dibujar_mundo_isom(BITMAP *mapa_destino, int x0, int y0);.
Devuelve: 0 si funcionó, -1 si falló.

int ism_coords_2d_a_iso(int *xiso, int *yiso, int *ziso, int x2d, int y2d, int vfija, unsigned char cfija);
Descripción: Transforma coordenadas 2d en sus equivalentes 3d. Es decir, indica cuál es el punto isométrico alineado con un punto 2d del mapa en el que dibujas el mundo isométrico, y que pertenece a un plano determinado.
Parámetros: xiso, yiso, ziso: punteros a las variables donde quieres almacenar las coordenadas isométricas.
x2d, y2d: la x e y del punto 2d.
vfija, cfija: el plano que contiene el punto isométrico. Debe ser paralelo al plano x, y o z, por lo que cfija debe valer D_X, D_Y o D_Z, y vfija será la coordenada de dicho plano.
Comentarios: Date cuenta de que un punto 2d no se corresponde con un único punto isométrico, sino con toda una recta perpendicular a la imagen. Por ello, para obtener un único punto, hay que intersectar esta recta con un plano, que es el que debes indicar a la función con sus dos últimos parámetros. Por ejemplo, para hallar el punto isométrico del suelo correspondiente a tu punto 2d, vfija debe valer 0, y cfija D_Z.
Devuelve: 0 si funcionó, -1 si falló.


- Sombras

     Al colocar nuevos objetos, podemos indicar la forma de la sombra que estos objetos proyectan sobre los otros objetos situados justo debajo y sobre el suelo, mediante el uso del parámetro sombra. Este parámetro es un mapa de bits que debe contener una máscara que indique la forma de dicha sombra. La intensidad con que las sombras son dibujadas es, por defecto, de un 50%, pero este porcentaje se puede cambiar mediante la siguiente función:

int ism_establecer_sombras(char sombras);
Descripción: Establece el porcentaje de sombreado entre un 0% (sin sombras) y un 100% (sombras totalmente negras).
Parámetros: sombras: porcentaje de sombreado a aplicar.
Devuelve: 0 si funcionó, -1 si falló.


- Objetos transparentes

     Otra de las posibilidades de los objetos libres, es la de que tengan un determinado nivel de transparencia. Todos los objetos libres tienen por defecto un 0% de transparencia cuando son creados, pero puedes variar este porcentaje entre 0 (opaco) y 100 (totalmente invisible) con la función ism_cambiar_dato_objeto, indicando D_TRANSP como dato a modificar. También puedes consultar el porcentaje de transparencia de un objeto mediante la función ism_obtener_dato_objeto,indicando D_TRANSP como dato a consultar. Como detalle extra, y para aumentar el realismo, las sombras de los objetos transparentes se dibujan más tenues, en un grado que depende de cuán transparente séa el objeto.

     Para dibujar los objetos transparentes, Isomot utiliza las funciones estándar de Allegro. Como todos sabemos, estas no son especialmente rápidas, así que si quieres que Isomot use tus propias funciones, o las de alguna otra librería, como FBlend por ejemplo (recomiendo ésta especialmente, busca en www.allegro.cc para más información al respecto), se lo puedes indicar a Isomot mediante la siguiente función:

int ism_func_transp(void(*f_transp)(BITMAP *, BITMAP *, int, int, int));
Descripción: Establece la función que Isomot utilizará para dibujar los objetos transparentes.
Parámetros: f_transp: la función de transparencia a utilizar.
Comentarios: f_transp debe ser una función que devuelva void, y tome los siguientes parámetros: (BITMAP *org, BITMAP *dst, int x, int y, int fact), donde org y dst son el mapa origen y destino (es decir, que org es el mapa que se va a dibujar en dst), x e y son las coordenadas de dst donde se va a dibujar org, y fact es el factor de transparencia a aplicar, que puede tomar valores entre 0 (valor que corresponde a un 100% de transparencia) y 255 (que corresponde a un 0% de transparencia) Esto coincide exactamente con la declaración de la función fblend_trans de la librería FBlend, lo que no es ninguna casualidad ;). De este modo, si usas FBlend en tu proyecto, bastará con ejecutar la instrucción ism_func_transp(fblend_trans); para que Isomot la utilice para dibujar los objetos transparentes, en logar de las funciones propias de Allegro.
Devuelve: 0 si funcionó, -1 si falló.


- Dibujando la vista isométrica

     De acuerdo. Hemos definido la rejilla, hemos asignado mapas a las paredes y las losetas, y hemos insertado unos cuantos objetos. ¿Como hacemos ahora para ver el resultado de todo esto? Fácil. Tan solo tienes que llamar a la siguiente función:

int ism_dibujar_mundo_isom(BITMAP *mapa_destino, int x0, int y0);
Descripción: Dibuja la vista isométrica en un mapa dado.
Parámetros: mapa_destino: el mapa donde quieres que se dibuje la vista isométrica.
x0, y0: el punto de mapa_destino donde quieres que se dibuje el punto (0,0,0) de la vista.
Devuelve: 0 si funcionó, -1 si falló.

     Además de esto, Isomot te da la posibilidad de dibujar las habitaciones oscureciéndolas en un determinado porcentaje, para simular la noche, el apagado de una luz, o lo que quieras. Dicho porcentaje de oscurecimiento se le indica a Isomot mediante la siguiente función:

int ism_establecer_oscuridad(char oscuridad);
Descripción: Indica el porcentaje de oscurecimiento que Isomot debe aplicar al dibujar el mundo isométrico mediante la función ism_dibujar_mundo_isom.
Parámetros: oscuridad: porcentaje de oscurecimiento de 0 (no oscurecer) a 100 (completamente negro).
Devuelve: 0 si funcionó, -1 si falló.

     Hay que tener en cuenta que Isomot utiliza una optimización especial, llamada "rectángulos sucios", de modo que en cada llamada a ism_dibujar_mundo_isom únicamente se dibujan aquellas partes del mundo que han cambiado. Esto puede acelerar enormemente el funcionamiento del motor, pero también puede ocasionar algunos problemas si haces cosas raras, como dibujar el mundo isométrico en diferentes mapas de destino, o si borras el mapa de destino antes de cada llamada a ism_dibujar_mundo_isom. Si se da el caso, puedes evitar esto desactivando los rectángulos sucios usando para ello la siguiente función:

void ism_habilitar_rect_sucio(char habilitar);
Descripción: activa o desactiva la utilización de rectángulos sucios.
Parámetros: habilitar: indica si hay que habilitar (valor 1) o deshabilitar (valor 0) los rectángulos sucios (por defecto siempre están habilitados).
Devuelve: Nada.


- Errores

     Si una función devuelve un error, probablemente quieras saber qué fué mal. Puedes obtener una descripción del error llamando a la siguiente función:

char *ism_desc_error(void);
Descripción: Devuelve un puntero a una cadena de texto con la explicación del error (en español).
Parámetros: Ninguno
Devuelve: Una cadena con la explicación del error.


- El fichero ism_lng.h

     Como ya se ha mencionado antes, Isomot consta de un interface bilingüe inglés - español. Por defecto, puedes utilizar las funciones de ambos interfaces sin problemas, pero lo más lógico, ya que estás leyendo la versión española de la documentación, es que sólo tengas interés en usar las funciones en español. Si es así, puedes evitar que se compile el interface inglés, con la consiguiende reducción del tamaño del ejecutable generado y la consiguiente mejora de rendimiento, editando el fichero ism_lng, y eliminando la definición de ISM_ENG. Cierto que ninguna de las dos mejoras será espectacular, pero toda pequeña ayuda es siempre bienvenida.


- Resumen de funciones

     Lo que sigue es una lista, ordenada alfabeticamente, de todas las funciones del interface en español de isomot. Pincha en ellas para ver la descripción detallada de cada una.

ism_cambiar_dato_objeto(ism_id id, unsigned char dato, int valor, unsigned char modo);
ism_cambiar_mapa_objeto(ism_id id, BITMAP *mapa);
ism_cambiar_sombra_objeto(ism_id id, BITMAP *sombra);
ism_colisionado_con(ism_id id);
ism_colocar_loseta(BITMAP *mapa, int x, int y);
ism_colocar_objeto_libre(int x, int y, int z, int anchurax, int anchuray, int altura, BITMAP *mapa, BITMAP *sombra);
ism_colocar_objeto_rejilla(int x, int y, int z, int altura, BITMAP *mapa, BITMAP *sombra);
ism_colocar_pared(BITMAP *mapa, unsigned char eje, int pared);
ism_colocar_suelo(BITMAP *mapa);
ism_coords_2d_a_iso(int *xiso, int *yiso, int *ziso, int x2d, int y2d, int vfija, unsigned char cfija);
ism_coords_iso_a_2d(int xiso, int yiso, int ziso, int *x2d, int *y2d);
ism_desc_error(void);
ism_destruir_todo(void);
ism_dibujar_mundo_isom(BITMAP *mapa_destino, int x0, int y0);
ism_establecer_rejilla(int x, int y, int anchura);
ism_establecer_oscuridad(char oscuridad);
ism_establecer_sombras(char sombras);
ism_existe_objeto(ism_id id);
ism_extraer_id_blq(void);
ism_func_transp(void(*f_transp)(BITMAP *, BITMAP *, int, int, int));
ism_habilitar_rect_sucio(char habilitar);
ism_mover_loseta(int x, int y, int despx, int despy);
ism_mover_objeto(ism_id id, int x, int y, int z, unsigned char modo);
ism_mover_pared(unsigned char eje, int pared, int despeje, int despaltura);
ism_mover_suelo(int despx, int despy);
ism_num_colisiones(void);
ism_obtener_coords_celda(int x, int y, int *xc, int *yc);
ism_obtener_coords_libres(int x, int y, int *xl, int *yl);
ism_obtener_coords_objeto(ism_id id, int *dstx, int *dsty, int *dstz);
ism_obtener_dato_objeto(ism_id id, unsigned char dato);
ism_quitar_objeto(ism_id id);
ism_vaciar_mundo_isom(void);


- Consejos

     El primero de todos, procura mantener la rejilla lo más pequeña posible, así como el número más reducido posible de objetos. De este modo el motor usará menos memoria y funcionará más rápido (obvio, ¿verdad?).

     Se pueden hacer bastantes menos cosas con los objetos rejilla que con los libres, pero no hay nada que puedas hacer con un rejilla que no puedas hacer con un libre, así que probablemente sientas la tentación de definir todos los objetos como libres y dejarte de historias. ¡No lo hagas! Los objetos rejilla se manejan mucho más rápido y ocupan mucha menos memoria que los libres.

     Si vas a trabajar con varios objetos sucesivamente, no empieces con uno hasta que no hayas terminado con el anterior. Por ejemplo:
     x1=ism_obtener_dato_objeto(obj1,D_X);
     ism_cambiar_dato_objeto(obj1,x1+1,D_X);
     x2=ism_obtener_dato_objeto(obj2,D_X);
     ism_cambiar_dato_objeto(obj2,x2+1,D_X);
   funcionará mucho más rápido que:
     x1=ism_obtener_dato_objeto(obj1,D_X);
     x2=ism_obtener_dato_objeto(obj2,D_X);
     ism_cambiar_dato_objeto(obj1,D_X,x1+1);
     ism_cambiar_dato_objeto(obj2,D_X,x2+1);

     El proceso que dibuja las sombras está optimizado para ciertos porcentajes de sombreado con los que funcionará bastante más rápido. Estos porcentajes son, para mapas de 24 y 32 bits de color, 50%, 75%, 87%, 93%, 97%, 98%, 99% y 100%, y para 15 y 16 bits, 47%, 48%, 49%, 50%, 72%, 73%, 74%, 75%, 85%, 86%, 87%, 91%, 92%, 93%, 97%, 98%, 99%, y 100%. Ya se que parece bastante raro, pero hay una razón lógica para que séan estos porcentajes los que se puedan optimizar, y no otros ;)

     Las posibilidades de la función ism_func_transp van mucho más allá de la de hacer más rápido el dibujado de los objetos transparentes; puedes escribir tu propia función y jugar con el nivel de transparencia de los objetos para aplicarles efectos especiales, como oscurecerlos, dibujarlos en blanco y negro, transparentar solo ciertas componentes del color, o cualquier otra cosa que se te ocurra.


- Historia

* 18/05/2008 v1.0.
- Añadidas las funciones ism_coords_iso_a_2d and ism_coords_2d_a_iso, para convertir entre coordenadas 2d de imágen y 3d isométricas.
- Los rectángulos sucios están ahora desactivados por defecto. Si los quieres, tendrás que activarlos llamando a ism_habilitar_rect_sucio.
- Incrementada la compatibilidad con C++.
- Arreglados un par de fallos menores aquí y allá.

* 27/05/2005 vb0.5.
- Añadidas las funciones ism_colocar_suelo, para poder dibujar el suelo con una sola imágen, además de como un mosáico de losetas, e ism_mover_suelo, para poder mover este nuevo suelo.
- Añadida la función ism_establecer_oscuridad, para definir el porcentaje de oscurecimiento con el que se dibujará la habitación.
- Añadida la optimización por rectángulos sucios, así como la función ism_habilitar_rect_sucio, para desactivarlos si es necesario.
- Arreglados un par de fallos sin importancia.

* 02/11/2004 vb0.4.
- Esta versión nunca llegó a hacerse pública; tan solo tenía un par de modificaciones sin importancia.

* 01/08/2003 vb0.3.
- Añadidas las funciones ism_colisionado_con e ism_num_colisiones, para facilitar el control de colisiones (gracias a Ron Ophir por darme la idéa).
- Soporte para objetos transparentes.
- Optimizado el proceso de dibujado de sombras.

* 30/04/2003 vb0.2.
- Soporte para mapas con cualquier profundidad de color.
- Añadido el fichero inm_lng.h para la optimización de los interfaces.
- Desde el principio, Isomot estaba pensado como un proyecto C, pero inadvertidamente lo estuve compilando siempre como C++, por lo que al querer compilarlo como C aparecieron bastantes errores que antes no se mostraban. Todos estos están ya arreglados (gracias a Neil Walker por ponerme sobre la pista de esto).
- Un par de pequeñas optimizaciones y algún error arreglado sin mayor importancia.

* 22/03/2003 vb0.1
- Primera versión beta diatribuida.


- Agradecimientos

     Muchas personas me han ayudado en la realización de este proyecto, sobre todo mis colegas de Retrospec: a Tomaz Kac le debo el método de sombreado por enmascaramiento, el logo de Isomot está basado en una idéa de Dan Condon-Jones, Neil Walker me ha ayudado a optimizar y depurar el código, y todos los demás, Arif Majothi, Bill Harbison, Graham Goring, Jeff Brayne, John Dow, Matthew Smith, Peter Jovanovic, Richard Jordan y Russ Hoy, me han ayudado mucho con sus comentarios y su apoyo. También Iñaki Martínez y Ron Ophir han aportado sus valiosas sugerencias y cooperación. Y también quiero dar las gracias a todas aquellas personas que me han escrito para interesarse por el proyecto y animarme a terminarlo.


©2008 - Ignacio Pérez Gil
Logo de Ignacio's SP Remakes por Ric Lumb.

Estas páginas están amablemente alojadas en  NETSI