Diferencias
Muestra las diferencias entre dos versiones de la página.
Ambos lados, revisión anterior Revisión previa Próxima revisión | Revisión previa Próxima revisiónAmbos lados, revisión siguiente | ||
cursos:z88dk:sprites3 [10-08-2007 08:20] – sromero | cursos:z88dk:sprites3 [10-08-2007 08:33] – sromero | ||
---|---|---|---|
Línea 15: | Línea 15: | ||
Durante los siguientes artículos nos centraremos especialmente en el módulo de sprites, con la idea de ser utilizado en el seno de nuestras aplicaciones z88dk para Spectrum, aunque durante el desarrollo de nuestros ejemplos tendremos que ir usando también algunas pequeñas partes del resto de los módulos. Vamos a dar un pequeño paso atrás con respecto a entregas anteriores, pues vamos a aprender de nuevo a dibujar sprites desde el principio, aunque utilizando Sprite Pack en esta ocasión. Podría parecer que esto es un poco inútil, pero ya veremos más adelante que las ventajas de utilizar esta capa por encima de z88dk no tardarán en llegar. | Durante los siguientes artículos nos centraremos especialmente en el módulo de sprites, con la idea de ser utilizado en el seno de nuestras aplicaciones z88dk para Spectrum, aunque durante el desarrollo de nuestros ejemplos tendremos que ir usando también algunas pequeñas partes del resto de los módulos. Vamos a dar un pequeño paso atrás con respecto a entregas anteriores, pues vamos a aprender de nuevo a dibujar sprites desde el principio, aunque utilizando Sprite Pack en esta ocasión. Podría parecer que esto es un poco inútil, pero ya veremos más adelante que las ventajas de utilizar esta capa por encima de z88dk no tardarán en llegar. | ||
+ | |||
Línea 29: | Línea 30: | ||
Sprite Pack incluye un fichero Makefile.bat que creará la librería en una máquina Windows. Solamente sería necesario en este tipo de entorno que se abriera una ventana de MS-DOS, se acudiera al directorio donde está el código fuente, y tras inicializar las variables de entorno que permiten compilar con z88dk, teclear Makefile. En Linux es un poco más complicado, y deberemos modificar ese archivo para que funcione. Para ahorrar trabajo al lector, se incluye un fichero Makefile.sh, | Sprite Pack incluye un fichero Makefile.bat que creará la librería en una máquina Windows. Solamente sería necesario en este tipo de entorno que se abriera una ventana de MS-DOS, se acudiera al directorio donde está el código fuente, y tras inicializar las variables de entorno que permiten compilar con z88dk, teclear Makefile. En Linux es un poco más complicado, y deberemos modificar ese archivo para que funcione. Para ahorrar trabajo al lector, se incluye un fichero Makefile.sh, | ||
- | Sea cual sea el sistema operativo que utilicemos, como resultado obtendremos un nuevo fichero **splib2.lib**, | + | Sea cual sea el sistema operativo que utilicemos, como resultado obtendremos un nuevo fichero **splib2.lib**, |
===== Nuestro primer ejemplo ===== | ===== Nuestro primer ejemplo ===== | ||
Línea 36: | Línea 38: | ||
Sprite Pack tiene una forma particular de actualizar la pantalla. Realizar una actualización completa y simultánea de toda ella simultáneamente haría necesario el uso de rutinas en ensamblador demasiado específicas, | Sprite Pack tiene una forma particular de actualizar la pantalla. Realizar una actualización completa y simultánea de toda ella simultáneamente haría necesario el uso de rutinas en ensamblador demasiado específicas, | ||
- | Otros conceptos que deberemos tener claros son el de backtile y sprite. Comprender la diferencia entre ambos es necesario para desarrollar nuestras aplicaciones. La pantalla está dividida en un array de tamaño 32x24 de celdas de caracteres (a su vez de tamaño 8x8). Cada una de estas celdas podrá contener sólo un backtile y uno o más sprites. Los backtiles se pueden entender como el " | + | Otros conceptos que deberemos tener claros son el de **backtile** y **sprite**. Comprender la diferencia entre ambos es necesario para desarrollar nuestras aplicaciones. La pantalla está dividida en un array de tamaño 32x24 de celdas de caracteres (a su vez de tamaño 8x8). Cada una de estas celdas podrá contener sólo un backtile y uno o más sprites. Los backtiles se pueden entender como el " |
- | De momento nos centraremos en los backtiles. La función básica para dibujarlos es sp_PrintAtInv, | + | De momento nos centraremos en los backtiles. La función básica para dibujarlos es **sp_PrintAtInv**, que además de dibujar el carácter con el color de tinta y papel que deseemos, |
Veamos un ejemplo. El siguiente código se encarga de dibujar letras ' | Veamos un ejemplo. El siguiente código se encarga de dibujar letras ' | ||
- | + | <code c> | |
- | #include | + | # |
- | # | + | # |
#pragma output STACKPTR=61440 | #pragma output STACKPTR=61440 | ||
Línea 70: | Línea 72: | ||
} | } | ||
} | } | ||
+ | </ | ||
Veamos línea por línea de qué va todo esto. Las dos primeras se corresponden con las sentencias #include necesarias; en este caso la librería estándar y el archivo de cabecera de la librería Sprite Pack. | Veamos línea por línea de qué va todo esto. Las dos primeras se corresponden con las sentencias #include necesarias; en este caso la librería estándar y el archivo de cabecera de la librería Sprite Pack. | ||
- | La sentencia #pragma deberemos incluirla siempre al principio de nuestros programas escritos para la librería Sprite Pack, antes del método main. Lo que se dice con ella es que se desea comenzar la ejecución del programa con el puntero de la pila del Z80 apuntando a la dirección 61440. Al hacerlo de esta forma, evitaremos que la función sp_initialize destruya cierta información de la memoria. | + | La sentencia |
Las primeras líneas de código en el interior de main(), entre el primer #asm y el último #endasm tendremos que ponerlas también siempre en nuestros programas que usen Sprite Pack. No es necesario entrar en detalle, pero diremos que este código tiene algo que ver con deshabilitar interrupciones para que ciertas funciones como sp_Invalidate funcionen. | Las primeras líneas de código en el interior de main(), entre el primer #asm y el último #endasm tendremos que ponerlas también siempre en nuestros programas que usen Sprite Pack. No es necesario entrar en detalle, pero diremos que este código tiene algo que ver con deshabilitar interrupciones para que ciertas funciones como sp_Invalidate funcionen. | ||
- | Y por fin comienzan las líneas interesantes. La función sp_Initialize es necesaria para que el módulo de sprites de la librería comience a funcionar. En este caso, los parámetros hacen que la pantalla se inicialice escribiendo espacios en blanco, con color de fondo (paper) blanco y tinta negra (ink). | + | Y por fin comienzan las líneas interesantes. La función |
- | A continuación nos introducimos en el bucle principal, que se va a ejecutar de forma ininterrumpida por toda la eternidad (a menos que detengamos la ejecución del programa). La estructura es muy sencilla. Primero se llama a sp_UpdateNow para que se redibujen las celdas de la pantalla donde hubo algún cambio. A continuación se obiene un número al azar entre 1 y 10 (mediante la función rand()), y en función de su valor llamaremos a sp_PrintAtInv | + | A continuación nos introducimos en el bucle principal, que se va a ejecutar de forma ininterrumpida por toda la eternidad (a menos que detengamos la ejecución del programa). La estructura es muy sencilla. Primero se llama a **sp_UpdateNow** para que se redibujen las celdas de la pantalla donde hubo algún cambio. A continuación se obiene un número al azar entre 1 y 10 (mediante la función rand()), y en función de su valor llamaremos a s**p_PrintAtInv** |
El método sp_PrintAtInv dibuja un backtile en la pantalla e invalida la posición donde dicho backtile ha sido colocado, para que la celda correspondiente sea redibujada tras llamar a sp_UpdateNow. Los dos primeros parámetros indican la posición del backtile (que también los obtenemos al azar), a continuación el color de papel y de tinta (con la misma sintaxis que en el caso de la función sp_Initialize) y por último indicamos el carácter a escribir. Este carácter se corresponde con un UDG, como en BASIC. De momento no hemos asociado ningún UDG a la letra x, por lo que se mostrará en pantalla será la letra x apareciendo en posiciones al azar, teniendo o bien color de tinta rojo y papel cyan o al revés. | El método sp_PrintAtInv dibuja un backtile en la pantalla e invalida la posición donde dicho backtile ha sido colocado, para que la celda correspondiente sea redibujada tras llamar a sp_UpdateNow. Los dos primeros parámetros indican la posición del backtile (que también los obtenemos al azar), a continuación el color de papel y de tinta (con la misma sintaxis que en el caso de la función sp_Initialize) y por último indicamos el carácter a escribir. Este carácter se corresponde con un UDG, como en BASIC. De momento no hemos asociado ningún UDG a la letra x, por lo que se mostrará en pantalla será la letra x apareciendo en posiciones al azar, teniendo o bien color de tinta rojo y papel cyan o al revés. | ||
- | La última línea del bucle, sp_Pause, introduce un pequeño retardo. Actúa exactamente igual que el comando PAUSE de BASIC. | + | La última línea del bucle, |
- | Espectaculares efectos gráficos conseguidos con la librería Sprite Pack | + | |
- | Espectaculares efectos gráficos conseguidos con la librería Sprite Pack | + | |
- | NUESTRO PRIMER EJEMPLO CON UN SPRITE | + | {{ cursos: |
- | En esta sección vamos a dibujar un sprite simple sobre un fondo un poco más complejo. Para comprender cómo podemos crear un fondo más complejo, hemos de recordar que los backtiles pueden entenderse como si fueran UDGs de BASIC; sin embargo, hasta ahora solo hemos utilizado caracteres alfanuméricos. ¿De qué forma definimos gráficos para estos backtiles? | ||
- | Mediante la función sp_TileArray asociamos | + | ===== Nuestro primer ejemplo con un Sprite ===== |
+ | |||
+ | |||
+ | En esta sección vamos a dibujar | ||
+ | Mediante la función **sp_TileArray** asociamos un determinado UDG 8x8 a un carácter, de tal forma que al escribir dicho carácter como backtile en la pantalla, aparecerá su UDG correspondiente. Esta función recibe como parámetro el carácter al que queremos asociar el UDG y un array de tipo uchar con la definición del UDG. Ese array contendrá un valor hexadecimal por cada fila del UDG, utilizando la misma notación que vimos en capítulos anteriores para la creación de sprites de tamaño 8x8 con z88dk. Por ejemplo, observemos el siguiente código: | ||
+ | <code c> | ||
uchar fondo[] = {0x55, | uchar fondo[] = {0x55, | ||
sp_TileArray(' | sp_TileArray(' | ||
sp_Initialize(INK_WHITE | PAPER_BLACK, | sp_Initialize(INK_WHITE | PAPER_BLACK, | ||
+ | </ | ||
Con la primera línea creamos un array llamado fondo que contendrá la definición de un UDG de tipo " | Con la primera línea creamos un array llamado fondo que contendrá la definición de un UDG de tipo " | ||
Línea 103: | Línea 109: | ||
¿Y cómo definimos un sprite? De forma mucho más fácil a la vista en artículos anteriores, en los que se usaba z88dk sin ningún añadido. Nada más simple que una notación como la siguiente: | ¿Y cómo definimos un sprite? De forma mucho más fácil a la vista en artículos anteriores, en los que se usaba z88dk sin ningún añadido. Nada más simple que una notación como la siguiente: | ||
+ | <code c> | ||
#asm | #asm | ||
Línea 117: | Línea 123: | ||
#endasm | #endasm | ||
+ | </ | ||
Como se puede observar, volvemos a hacer uso de código ensamblador empotrado en el interior de nuestro código C, entre las directivas #asm y #endasm. En este caso concreto estamos definiendo un único sprite 8x8, para el cual necesitaremos dos bloques de bits de ese tamaño. El de la izquierda es el dibujo en sí mismo del sprite, que en nuestro caso en una pequeña carita con la boca abierta. El bloque de la derecha indica las transparencias; | Como se puede observar, volvemos a hacer uso de código ensamblador empotrado en el interior de nuestro código C, entre las directivas #asm y #endasm. En este caso concreto estamos definiendo un único sprite 8x8, para el cual necesitaremos dos bloques de bits de ese tamaño. El de la izquierda es el dibujo en sí mismo del sprite, que en nuestro caso en una pequeña carita con la boca abierta. El bloque de la derecha indica las transparencias; | ||
Línea 122: | Línea 129: | ||
A este bloque de datos que marcan un sprite de 8x8 le hemos llamado sprite1. Este nombre nos servirá para referenciar este código ensamblador desde el código C. Para ver cómo dibujar el sprite en la pantalla, nada mejor que un pequeño ejemplo: | A este bloque de datos que marcan un sprite de 8x8 le hemos llamado sprite1. Este nombre nos servirá para referenciar este código ensamblador desde el código C. Para ver cómo dibujar el sprite en la pantalla, nada mejor que un pequeño ejemplo: | ||
- | + | <code c> | |
- | # | + | # |
#pragma output STACKPTR=61440 | #pragma output STACKPTR=61440 | ||
Línea 135: | Línea 142: | ||
extern uchar sprite1[]; | extern uchar sprite1[]; | ||
uchar fondo[] = {0x55, | uchar fondo[] = {0x55, | ||
- | |||
Línea 151: | Línea 157: | ||
main() | main() | ||
{ | { | ||
- | struct sp_SS *bicho; | + | struct sp_SS *bicho; |
+ | #asm | ||
+ | di | ||
+ | # | ||
+ | | ||
+ | | ||
+ | #asm | ||
+ | ei | ||
+ | # | ||
- | # | + | |
- | di | + | sp_Initialize(INK_WHITE | PAPER_BLACK, |
- | #endasm | + | sp_Border(BLACK); |
- | | + | sp_AddMemory(0, |
- | sp_CreateGenericISR(0xf1f1); | + | |
- | #asm | + | |
- | ei | + | |
- | # | + | |
- | | + | bicho = sp_CreateSpr(sp_MASK_SPRITE, 1, sprite1, 1, TRANSPARENT); |
- | sp_Initialize(INK_WHITE | PAPER_BLACK, ' '); | + | sp_MoveSprAbs(bicho, sp_ClipStruct, 0, 10, 15, 0, 0); |
- | | + | |
- | | + | |
- | bicho = sp_CreateSpr(sp_MASK_SPRITE, | + | sp_UpdateNow(); |
- | | + | |
- | + | ||
- | sp_UpdateNow(); | + | |
- | while(1); | + | while(1); |
} | } | ||
Línea 189: | Línea 194: | ||
#endasm | #endasm | ||
+ | </ | ||
Comentemos línea por línea el programa. La sentencia #pragma ya la conocemos del ejemplo anterior, así que no hace falta que nos detengamos en ella. A continuación se define una estructura de la forma siguiente: | Comentemos línea por línea el programa. La sentencia #pragma ya la conocemos del ejemplo anterior, así que no hace falta que nos detengamos en ella. A continuación se define una estructura de la forma siguiente: | ||
+ | <code c> | ||
extern struct sp_Rect *sp_ClipStruct; | extern struct sp_Rect *sp_ClipStruct; | ||
#asm | #asm | ||
Línea 198: | Línea 204: | ||
._sp_ClipStruct | ._sp_ClipStruct | ||
#endasm | #endasm | ||
+ | </ | ||
Esta estructura tan confusa está sacada de spritepack.h y define un rectángulo que cubre toda la superficie de la pantalla. Existen muchas definiciones como ésta dentro de dicho fichero de cabecera. Para qué sirven lo veremos mucho más adelante, cuando tratemos el tema de las colisiones. De momento deberemos saber que lo necesitamos para poder dibujar el sprite en la pantalla. | Esta estructura tan confusa está sacada de spritepack.h y define un rectángulo que cubre toda la superficie de la pantalla. Existen muchas definiciones como ésta dentro de dicho fichero de cabecera. Para qué sirven lo veremos mucho más adelante, cuando tratemos el tema de las colisiones. De momento deberemos saber que lo necesitamos para poder dibujar el sprite en la pantalla. | ||
- | La línea extern uchar sprite1[]; crea el array que contendrá la información del sprite. Este array se llena con los datos definidos entre las cláusulas #asm y #endasm al final del programa, después de la etiqueta ._sprite1, y contendrá la definición del sprite, de la misma forma en la que en la línea siguiente se crea un array de tipo uchar llamado fondo con la definición de un UDG para asociarlo al backtile de fondo. | + | La línea |
El siguiente código: | El siguiente código: | ||
+ | <code c> | ||
void *my_malloc(uint bytes) | void *my_malloc(uint bytes) | ||
{ | { | ||
Línea 214: | Línea 221: | ||
void *u_malloc = my_malloc; | void *u_malloc = my_malloc; | ||
void *u_free = sp_FreeBlock; | void *u_free = sp_FreeBlock; | ||
+ | </ | ||
entra dentro de lo que estaremos obligados a insertar en nuestro programa cada vez que queramos añadirle sprites, aunque no entendamos muy bien de qué se trata. Se obtiene a partir del módulo de manejo de memoria de Sprite Pack y sirve para que el programa pueda obtener memoria bajo demanda. Esto es necesario debido a la forma en que la pantalla es actualizada al usar esta librería. Además de las estructuras creadas por el programador, | entra dentro de lo que estaremos obligados a insertar en nuestro programa cada vez que queramos añadirle sprites, aunque no entendamos muy bien de qué se trata. Se obtiene a partir del módulo de manejo de memoria de Sprite Pack y sirve para que el programa pueda obtener memoria bajo demanda. Esto es necesario debido a la forma en que la pantalla es actualizada al usar esta librería. Además de las estructuras creadas por el programador, | ||
- | Y por fin comienza el método main. En primer lugar definimos la variable que va a contener el sprite que vamos a mostrar por pantalla. Esta variable es de tipo struct sp_SS, una estructura que contiene diversa infomación sobre un sprite, como su localización y su tamaño. A continuación, | + | Y por fin comienza el método |
Y continuamos con las dos líneas siguientes, cuyo funcionamiento ha sido explicado anteriormente: | Y continuamos con las dos líneas siguientes, cuyo funcionamiento ha sido explicado anteriormente: | ||
+ | <code c> | ||
p_TileArray(' | p_TileArray(' | ||
sp_Initialize(INK_WHITE | PAPER_BLACK, | sp_Initialize(INK_WHITE | PAPER_BLACK, | ||
+ | </ | ||
- | La línea posterior es nueva, y permite definir el color del borde de la pantalla (como la instrucción BORDER de BASIC). A continuación otra línea un tanto complicada, correspondiente a la llamada a la función sp_AddMemory, | + | La línea posterior es nueva, y permite definir el color del borde de la pantalla (como la instrucción BORDER de BASIC). A continuación otra línea un tanto complicada, correspondiente a la llamada a la función |
Las líneas que más nos interesan de este ejemplo son las siguientes: | Las líneas que más nos interesan de este ejemplo son las siguientes: | ||
+ | <code c> | ||
bicho = sp_CreateSpr(sp_MASK_SPRITE, | bicho = sp_CreateSpr(sp_MASK_SPRITE, | ||
sp_MoveSprAbs(bicho, | sp_MoveSprAbs(bicho, | ||
+ | </ | ||
- | Con la primera de ellas creamos el sprite en si mismo. El resultado de la llamada se almacenará en la variable de tipo struct sp_SS bicho declarada anteriormente, | + | Con la primera de ellas creamos el sprite en si mismo. El resultado de la llamada se almacenará en la variable de tipo struct sp_SS bicho declarada anteriormente, |
- | Situaremos el sprite creado sobre la pantalla mediante el uso de la función sp_MoveSprAbs, | + | Situaremos el sprite creado sobre la pantalla mediante el uso de la función |
Como primer parámetro, el sprite a mover. Como segundo parámetro, el rectángulo que hace referencia a toda la pantalla definido anteriormente. El tercer parámetro hace referencia a la animación, y tampoco hablaremos de él en esta ocasión. El cuarto y el quinto, al bloque de la pantalla donde situaremos el sprite. Decíamos anteriormente que la pantalla estaba dividida en bloques de 8x8; pues bien, con estos dos parámetros indicamos la celda donde colocaremos nuestro sprite. Para conseguir una colocación más exacta, podemos usar los dos últimos parámetros, | Como primer parámetro, el sprite a mover. Como segundo parámetro, el rectángulo que hace referencia a toda la pantalla definido anteriormente. El tercer parámetro hace referencia a la animación, y tampoco hablaremos de él en esta ocasión. El cuarto y el quinto, al bloque de la pantalla donde situaremos el sprite. Decíamos anteriormente que la pantalla estaba dividida en bloques de 8x8; pues bien, con estos dos parámetros indicamos la celda donde colocaremos nuestro sprite. Para conseguir una colocación más exacta, podemos usar los dos últimos parámetros, | ||
- | Por último, con sp_UpdateNow() redibujamos las porciones de la pantalla que lo necesiten, y con while(1) dejamos nuestro programa en constante ejecución, hasta el resto de los días, o hasta que lo detengamos. El resultado se puede observar en la siguiente captura de pantalla. | + | Por último, con **sp_UpdateNow()** redibujamos las porciones de la pantalla que lo necesiten, y con while(1) dejamos nuestro programa en constante ejecución, hasta el resto de los días, o hasta que lo detengamos. El resultado se puede observar en la siguiente captura de pantalla. |
- | Un terrible ser intergaláctico espera ansioso la orden de atacar | + | |
- | Un terrible ser intergaláctico espera ansioso la orden de atacar | + | {{ cursos: |
+ | |||
+ | |||
+ | |||
+ | |||
+ | ===== Un sprite grande y nervioso ===== | ||
- | UN SPRITE GRANDE Y NERVIOSO | ||
En este apartado veremos un pequeño ejemplo que introduce algunos conceptos interesantes, | En este apartado veremos un pequeño ejemplo que introduce algunos conceptos interesantes, | ||
Línea 251: | Línea 265: | ||
Por ejemplo, mostramos como quedaría un sprite con un tamaño de dos bloques de alto por dos bloques de ancho listo para ser usado con Sprite Pack: | Por ejemplo, mostramos como quedaría un sprite con un tamaño de dos bloques de alto por dos bloques de ancho listo para ser usado con Sprite Pack: | ||
+ | <code c> | ||
#asm | #asm | ||
Línea 293: | Línea 307: | ||
#endasm | #endasm | ||
+ | </ | ||
Como se puede observar, definimos dos columnas para el sprite, cada una de ellas formada a su vez por dos sprites de tamaño 8x8, incluyendo su máscara de transparencias. Para utilizar el sprite en el código deberíamos hacer algo similar a esto: | Como se puede observar, definimos dos columnas para el sprite, cada una de ellas formada a su vez por dos sprites de tamaño 8x8, incluyendo su máscara de transparencias. Para utilizar el sprite en el código deberíamos hacer algo similar a esto: | ||
+ | <code c> | ||
extern uchar bicho1[]; | extern uchar bicho1[]; | ||
extern uchar bicho2[]; | extern uchar bicho2[]; | ||
Línea 308: | Línea 323: | ||
| | ||
} | } | ||
+ | </ | ||
- | Se debe hacer uso, en primer lugar, de sp_CreateSpr para asignar la primera columna del sprite a la variable de tipo struct sp_SS, y en segundo lugar, de sp_AddColSpr, | + | Se debe hacer uso, en primer lugar, de **sp_CreateSpr** para asignar la primera columna del sprite a la variable de tipo **struct sp_SS**, y en segundo lugar, de **sp_AddColSpr**, tantas veces como columnas adicionales debamos añadir. En este caso, se ha usado un valor de 2 para el segundo parámetro de sp_CreateSpr, |
Es importante destacar que todas las columnas de un mismo sprite deben de ser definidas de forma contigua en la memoria. Esto se traduce en que tenemos que definirlas de forma contigua también en nuestro código. | Es importante destacar que todas las columnas de un mismo sprite deben de ser definidas de forma contigua en la memoria. Esto se traduce en que tenemos que definirlas de forma contigua también en nuestro código. | ||
Línea 315: | Línea 331: | ||
Sin embargo, hay algo que hasta ahora no hemos tenido en cuenta, y es debido a que no hemos movido nuestros sprites por la pantalla. Cuando trasladamos sprites usando el pixel y no el bloque como unidad de medida (los dos últimos parámetros de sp_MoveSprAbs y sp_MoveSprRel servían para esto) veremos como los sprites no son correctamente dibujados; solo se redibuja la parte del sprite más a la izquierda que cabe dentro de una misma celdilla de la pantalla. Un truco para evitar esto es crear sprites un poco más anchos y más altos de lo que realmente necesitamos. Para ello, añadimos una nueva columna en blanco, y en cada columna, un nuevo bloque en blanco al final. En el caso concreto de nuestro sprite 2x2 anterior, deberíamos definirlo de esta forma: | Sin embargo, hay algo que hasta ahora no hemos tenido en cuenta, y es debido a que no hemos movido nuestros sprites por la pantalla. Cuando trasladamos sprites usando el pixel y no el bloque como unidad de medida (los dos últimos parámetros de sp_MoveSprAbs y sp_MoveSprRel servían para esto) veremos como los sprites no son correctamente dibujados; solo se redibuja la parte del sprite más a la izquierda que cabe dentro de una misma celdilla de la pantalla. Un truco para evitar esto es crear sprites un poco más anchos y más altos de lo que realmente necesitamos. Para ello, añadimos una nueva columna en blanco, y en cada columna, un nuevo bloque en blanco al final. En el caso concreto de nuestro sprite 2x2 anterior, deberíamos definirlo de esta forma: | ||
+ | <code c> | ||
#asm | #asm | ||
Línea 403: | Línea 419: | ||
#endasm | #endasm | ||
- | + | </ | |
Por lo tanto, nuestro sprite 2x2 se convierte en un sprite 3x3 al añadir una nueva columna a la derecha y un nuevo bloque en la parte inferior de cada columna. Nuestro código a la hora de usar el sprite debería ser en este caso algo más parecido a esto: | Por lo tanto, nuestro sprite 2x2 se convierte en un sprite 3x3 al añadir una nueva columna a la derecha y un nuevo bloque en la parte inferior de cada columna. Nuestro código a la hora de usar el sprite debería ser en este caso algo más parecido a esto: | ||
+ | <code c> | ||
extern uchar bicho1[]; | extern uchar bicho1[]; | ||
extern uchar bicho2[]; | extern uchar bicho2[]; | ||
Línea 421: | Línea 437: | ||
| | ||
} | } | ||
+ | </ | ||
Como queda patente, indicamos que el tamaño en bloques de cada columna es 3 al llamar a la función sp_CreateSPr, | Como queda patente, indicamos que el tamaño en bloques de cada columna es 3 al llamar a la función sp_CreateSPr, | ||
- | A continuación se muestra un ejemplo completo, con nuestro sprite moviéndose al azar por la pantalla, por medio de la función sp_MoveSprRel: | + | A continuación se muestra un ejemplo completo, con nuestro sprite moviéndose al azar por la pantalla, por medio de la función |
+ | <code c> | ||
+ | #include < | ||
+ | #include < | ||
- | # | ||
- | # | ||
#pragma output STACKPTR=61440 | #pragma output STACKPTR=61440 | ||
Línea 589: | Línea 607: | ||
#endasm | #endasm | ||
+ | </ | ||
Ya deberíamos entender la práctica totalidad de este código, que mueve un sprite al azar por la pantalla, por lo que tan solo haremos dos apuntes: | Ya deberíamos entender la práctica totalidad de este código, que mueve un sprite al azar por la pantalla, por lo que tan solo haremos dos apuntes: | ||
Línea 595: | Línea 614: | ||
* Se ha añadido un bloque vacío antes de definir nuestro sprite, al final del código anterior; esto es así porque debemos asegurarnos de que haya un bloque en blanco encima de cada columna (manías del ensamblador generado por Sprite Pack). | * Se ha añadido un bloque vacío antes de definir nuestro sprite, al final del código anterior; esto es así porque debemos asegurarnos de que haya un bloque en blanco encima de cada columna (manías del ensamblador generado por Sprite Pack). | ||
- | El terrible ser intergaláctico se ha hecho mayor y es más nervioso que antes... | + | {{ cursos: |
- | El terrible ser intergaláctico se ha hecho mayor y es más nervioso que antes... | + | |
===== ¿Y ahora qué? ===== | ===== ¿Y ahora qué? ===== | ||
Línea 606: | Línea 624: | ||
En el siguiente artículo añadiremos colores a nuestros sprites y aprenderemos a moverlos con el teclado. También veremos como borrar de forma efectiva un sprite. Si el espacio lo permite (y si no es así, que no cunda el pánico, pues se verá en números posteriores de la revista) codificaremos un simple juego funcional con todo lo aprendido. | En el siguiente artículo añadiremos colores a nuestros sprites y aprenderemos a moverlos con el teclado. También veremos como borrar de forma efectiva un sprite. Si el espacio lo permite (y si no es así, que no cunda el pánico, pues se verá en números posteriores de la revista) codificaremos un simple juego funcional con todo lo aprendido. | ||
+ | |||
===== Enlaces ===== | ===== Enlaces ===== | ||
- | * [[http:// | + | * [[http:// |