Diferencias
Muestra las diferencias entre dos versiones de la página.
Próxima revisión | Revisión previa | ||
cursos:z88dk:sprites4 [09-08-2007 13:47] – creado sromero | cursos:z88dk:sprites4 [24-02-2020 19:25] (actual) – falvarez | ||
---|---|---|---|
Línea 1: | Línea 1: | ||
- | http://www.speccy.org/ | + | |
+ | Publicado originalmente en [[https://magazinezx.speccy.org/ | ||
+ | |||
+ | ====== Sprites en Z88DK (IV) ====== | ||
+ | |||
+ | |||
+ | ===== La librería Sprite Pack (II) ===== | ||
+ | |||
+ | |||
+ | En la entrega anterior de la revista | ||
+ | |||
+ | En esta ocasión vamos a añadir un par de sencillos detalles más antes de comenzar a escribir nuestro propio juego; un código que luego podrá formar parte de un producto más elaborado. En concreto veremos cómo hacer reaccionar nuestro programa ante la pulsación de teclas por parte del usuario, y cómo mover un sprite utilizando este dispositivo de entrada. También aprenderemos como añadir color a los sprites. Para nuestras explicaciones haremos uso como base del código sprite2.c que se creó en la anterior entrega, y en el que se definía un sprite de tamaño 2x1 que se desplazaba al azar. | ||
+ | |||
+ | |||
+ | ===== Moviendo los sprites con el teclado ===== | ||
+ | |||
+ | Si queremos mover un sprite por la pantalla utilizando el teclado, lo primero que deberemos hacer en nuestro programa es declarar una estructura del siguiente tipo: | ||
+ | |||
+ | <code c> | ||
+ | struct sp_UDK keys; | ||
+ | </ | ||
+ | |||
+ | La variable keys nos permitirá asociar teclas de nuestro teclado con los diferentes controles de un joystick virtual haciendo uso de la función // | ||
+ | |||
+ | <code c> | ||
+ | keys.up = sp_LookupKey(' | ||
+ | keys.down = sp_LookupKey(' | ||
+ | keys.right = sp_LookupKey(' | ||
+ | keys.left = sp_LookupKey(' | ||
+ | keys.fire = sp_LookupKey(' | ||
+ | </ | ||
+ | |||
+ | Según este ejemplo, cada vez que pulsáramos ' | ||
+ | |||
+ | La función **sp_JoyKeyboard** devuelve una máscara de bits indicándonos qué controles del joystick están accionados en ese momento debido a que sus correspondientes teclas están pulsadas. La forma de interpretar el valor devuelto por esta función es igual que con cualquier máscara de bits en C, y se puede contemplar en el siguiente ejemplo, que consiste en el archivo // | ||
+ | |||
+ | <code c> | ||
+ | #include < | ||
+ | #include < | ||
+ | #pragma output STACKPTR=61440 | ||
+ | |||
+ | extern struct sp_Rect *sp_ClipStruct; | ||
+ | #asm | ||
+ | LIB SPCClipStruct | ||
+ | ._sp_ClipStruct | ||
+ | #endasm | ||
+ | |||
+ | extern uchar bicho1[]; | ||
+ | extern uchar bicho2[]; | ||
+ | extern uchar bicho3[]; | ||
+ | struct sp_UDK keys; // nuevo | ||
+ | |||
+ | uchar hash[] = {0x55, | ||
+ | |||
+ | void *my_malloc(uint bytes) | ||
+ | { | ||
+ | | ||
+ | } | ||
+ | |||
+ | void *u_malloc = my_malloc; | ||
+ | void *u_free | ||
+ | |||
+ | main() | ||
+ | { | ||
+ | char dx,dy,i | ||
+ | | ||
+ | |||
+ | |||
+ | #asm | ||
+ | di | ||
+ | #endasm | ||
+ | sp_InitIM2(0xf1f1); | ||
+ | sp_CreateGenericISR(0xf1f1); | ||
+ | #asm | ||
+ | ei | ||
+ | #endasm | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | |||
+ | // nuevo (principio) | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | // nuevo (fin) | ||
+ | |||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | |||
+ | | ||
+ | | ||
+ | |||
+ | // nuevo (principio) | ||
+ | | ||
+ | if ((i & sp_FIRE) | ||
+ | dx = dy = 1; | ||
+ | } else { | ||
+ | dx = dy = 8; | ||
+ | } | ||
+ | if ((i & sp_LEFT) == 0) | ||
+ | dx = -dx; | ||
+ | else if ((i & sp_RIGHT) != 0) | ||
+ | dx = 0; | ||
+ | if ((i & sp_UP) == 0) | ||
+ | dy = -dy; | ||
+ | else if ((i & sp_DOWN) != 0) | ||
+ | dy = 0; | ||
+ | // nuevo (fin) | ||
+ | |||
+ | | ||
+ | } | ||
+ | } | ||
+ | |||
+ | #asm | ||
+ | |||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | |||
+ | ._bicho1 | ||
+ | defb @00000011, @11111100 | ||
+ | defb @00000100, @11111000 | ||
+ | defb @00001000, @11110000 | ||
+ | defb @00001011, @11110000 | ||
+ | defb @00001011, @11110000 | ||
+ | defb @00001000, @11110000 | ||
+ | defb @00001000, @11110000 | ||
+ | defb @00000100, @11111000 | ||
+ | |||
+ | defb @00000011, @11111100 | ||
+ | defb @00001100, @11110011 | ||
+ | defb @00001100, @11110011 | ||
+ | defb @00011000, @11100111 | ||
+ | defb @00011000, @11100111 | ||
+ | defb @01111100, @10000011 | ||
+ | defb @01111100, @10000011 | ||
+ | defb @00000000, @11111111 | ||
+ | |||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | |||
+ | ._bicho2 | ||
+ | defb @11100000, @00011111 | ||
+ | defb @00010000, @00001111 | ||
+ | defb @00001000, @00000111 | ||
+ | defb @01101000, @00000111 | ||
+ | defb @01101000, @00000111 | ||
+ | defb @00001000, @00000111 | ||
+ | defb @10001000, @00000111 | ||
+ | defb @10010000, @00001111 | ||
+ | |||
+ | defb @11100000, @00011111 | ||
+ | defb @00011000, @11100111 | ||
+ | defb @00011000, @11100111 | ||
+ | defb @00001100, @11110011 | ||
+ | defb @00001100, @11110011 | ||
+ | defb @00111110, @11000001 | ||
+ | defb @00111110, @11000001 | ||
+ | defb @00000000, @11111111 | ||
+ | |||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | |||
+ | ._bicho3 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | |||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | |||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | |||
+ | #endasm | ||
+ | </ | ||
+ | |||
+ | Al probar el ejemplo nos habremos encontrado con un problema bastante grave: al no controlar cuándo el sprite sobrepasa los límites de la pantalla, es posible desplazar nuestro " | ||
+ | |||
+ | {{ cursos: | ||
+ | |||
+ | El código anterior se ha modificado para añadir dos nuevas funcionalidades. Al pulsar la tecla r, nuestro " | ||
+ | |||
+ | <code c> | ||
+ | #include < | ||
+ | #include < | ||
+ | #pragma output STACKPTR=61440 | ||
+ | |||
+ | extern struct sp_Rect *sp_ClipStruct; | ||
+ | #asm | ||
+ | LIB SPCClipStruct | ||
+ | ._sp_ClipStruct | ||
+ | #endasm | ||
+ | |||
+ | extern uchar bicho1[]; | ||
+ | extern uchar bicho2[]; | ||
+ | extern uchar bicho3[]; | ||
+ | struct sp_UDK keys; //NUEVO (TECLAS) | ||
+ | |||
+ | uchar hash[] = {0x55, | ||
+ | |||
+ | void *my_malloc(uint bytes) | ||
+ | { | ||
+ | | ||
+ | } | ||
+ | |||
+ | void *u_malloc = my_malloc; | ||
+ | void *u_free = sp_FreeBlock; | ||
+ | |||
+ | main() | ||
+ | { | ||
+ | char dx,dy,i | ||
+ | | ||
+ | uint reset, | ||
+ | int borde = 1; // nuevo | ||
+ | |||
+ | |||
+ | #asm | ||
+ | di | ||
+ | #endasm | ||
+ | sp_InitIM2(0xf1f1); | ||
+ | sp_CreateGenericISR(0xf1f1); | ||
+ | #asm | ||
+ | ei | ||
+ | #endasm | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | |||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | reset = sp_LookupKey(' | ||
+ | | ||
+ | |||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | |||
+ | | ||
+ | | ||
+ | | ||
+ | // TODO DENTRO DE ESTE WHILE ES NUEVO (TECLADO) MENOS EL UPDATE | ||
+ | | ||
+ | if ((i & sp_FIRE) == 0) { | ||
+ | dx = dy = 1; | ||
+ | } else { | ||
+ | dx = dy = 8; | ||
+ | } | ||
+ | if ((i & sp_LEFT) == 0) | ||
+ | dx = -dx; | ||
+ | else if ((i & sp_RIGHT) != 0) | ||
+ | dx = 0; | ||
+ | if ((i & sp_UP) == 0) | ||
+ | dy = -dy; | ||
+ | else if ((i & sp_DOWN) != 0) | ||
+ | dy = 0; | ||
+ | // nuevo (principio) | ||
+ | if (sp_KeyPressed(reset)) | ||
+ | | ||
+ | else | ||
+ | | ||
+ | if (sp_KeyPressed(cambioBorde)) | ||
+ | if (borde == 1) | ||
+ | { | ||
+ | borde = 2; | ||
+ | | ||
+ | } | ||
+ | | ||
+ | { | ||
+ | borde = 1; | ||
+ | | ||
+ | } | ||
+ | // nuevo (fin) | ||
+ | } | ||
+ | } | ||
+ | |||
+ | #asm | ||
+ | |||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | |||
+ | ._bicho1 | ||
+ | defb @00000011, @11111100 | ||
+ | defb @00000100, @11111000 | ||
+ | defb @00001000, @11110000 | ||
+ | defb @00001011, @11110000 | ||
+ | defb @00001011, @11110000 | ||
+ | defb @00001000, @11110000 | ||
+ | defb @00001000, @11110000 | ||
+ | defb @00000100, @11111000 | ||
+ | |||
+ | defb @00000011, @11111100 | ||
+ | defb @00001100, @11110011 | ||
+ | defb @00001100, @11110011 | ||
+ | defb @00011000, @11100111 | ||
+ | defb @00011000, @11100111 | ||
+ | defb @01111100, @10000011 | ||
+ | defb @01111100, @10000011 | ||
+ | defb @00000000, @11111111 | ||
+ | |||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | |||
+ | ._bicho2 | ||
+ | defb @11100000, @00011111 | ||
+ | defb @00010000, @00001111 | ||
+ | defb @00001000, @00000111 | ||
+ | defb @01101000, @00000111 | ||
+ | defb @01101000, @00000111 | ||
+ | defb @00001000, @00000111 | ||
+ | defb @10001000, @00000111 | ||
+ | defb @10010000, @00001111 | ||
+ | |||
+ | defb @11100000, @00011111 | ||
+ | defb @00011000, @11100111 | ||
+ | defb @00011000, @11100111 | ||
+ | defb @00001100, @11110011 | ||
+ | defb @00001100, @11110011 | ||
+ | defb @00111110, @11000001 | ||
+ | defb @00111110, @11000001 | ||
+ | defb @00000000, @11111111 | ||
+ | |||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | |||
+ | ._bicho3 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | |||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | |||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | |||
+ | #endasm | ||
+ | </ | ||
+ | |||
+ | Como veremos más adelante, deberemos implementar algún mecanismo para limitar la zona por donde nuestros sprites se van a desplazar. La forma de hacer esto es mediante simples comparaciones, | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ===== Añadiendo color ===== | ||
+ | |||
+ | |||
+ | Un paso importante para poder tener como resultado un videojuego vistoso y que entre por los ojos es aprovechar los colores de nuestro Spectrum y disponer de una combinación agradable de cromaticidad en los sprites de nuestro juego. Los colores también permitirán distinguir con mayor facilidad nuestro personaje de los enemigos y el resto de elementos de la pantalla. Ya vimos en entregas anteriores que en el caso de los tiles era bastante sencillo modificar la tonalidad de la tinta y el papel: | ||
+ | |||
+ | <code c> | ||
+ | sp_TileArray(' | ||
+ | sp_Initialize(INK_WHITE | PAPER_BLACK, | ||
+ | </ | ||
+ | |||
+ | pero en el caso de los sprites la cosa se complica un poco más y vamos a tener que dar unas cuantas " | ||
+ | |||
+ | El siguiente código muestra las modificaciones realizadas al programa anterior para poder añadirle color al sprite de nuestro bicho, y que pasaremos a explicar a continuación: | ||
+ | |||
+ | <code c> | ||
+ | #include < | ||
+ | #include < | ||
+ | #pragma output STACKPTR=61440 | ||
+ | |||
+ | extern struct sp_Rect *sp_ClipStruct; | ||
+ | #asm | ||
+ | LIB SPCClipStruct | ||
+ | ._sp_ClipStruct | ||
+ | #endasm | ||
+ | |||
+ | // nuevo (principio) | ||
+ | extern uchar *sp_NullSprPtr; | ||
+ | #asm | ||
+ | LIB SPNullSprPtr | ||
+ | ._sp_NullSprPtr | ||
+ | #endasm | ||
+ | // nuevo (fin) | ||
+ | |||
+ | extern uchar bicho1[]; | ||
+ | extern uchar bicho2[]; | ||
+ | extern uchar bicho3[]; | ||
+ | struct sp_UDK keys; | ||
+ | |||
+ | uchar hash[] = {0x55, | ||
+ | |||
+ | void *my_malloc(uint bytes) | ||
+ | { | ||
+ | | ||
+ | } | ||
+ | |||
+ | void *u_malloc = my_malloc; | ||
+ | void *u_free = sp_FreeBlock; | ||
+ | |||
+ | |||
+ | // nuevo (principio) | ||
+ | uchar n; | ||
+ | void addColour(struct sp_CS *cs) | ||
+ | { | ||
+ | if (n == 0) // Se rellena de arriba a abajo y de izquierda | ||
+ | | ||
+ | cs-> | ||
+ | else if (n == 1) | ||
+ | cs-> | ||
+ | else if (n == 2) | ||
+ | cs-> | ||
+ | else if (n == 3) | ||
+ | cs-> | ||
+ | else if (n == 4) | ||
+ | cs-> | ||
+ | else | ||
+ | | ||
+ | if (n > 5) | ||
+ | | ||
+ | n++; | ||
+ | | ||
+ | } | ||
+ | // nuevo (fin) | ||
+ | |||
+ | |||
+ | main() | ||
+ | { | ||
+ | char dx,dy,i | ||
+ | | ||
+ | uint reset, | ||
+ | int borde = 1; | ||
+ | |||
+ | |||
+ | #asm | ||
+ | di | ||
+ | #endasm | ||
+ | sp_InitIM2(0xf1f1); | ||
+ | sp_CreateGenericISR(0xf1f1); | ||
+ | #asm | ||
+ | ei | ||
+ | #endasm | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | |||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | reset = sp_LookupKey(' | ||
+ | | ||
+ | |||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | |||
+ | | ||
+ | | ||
+ | | ||
+ | |||
+ | | ||
+ | if ((i & sp_FIRE) == 0) { | ||
+ | dx = dy = 1; | ||
+ | } else { | ||
+ | dx = dy = 8; | ||
+ | } | ||
+ | if ((i & sp_LEFT) == 0) | ||
+ | dx = -dx; | ||
+ | else if ((i & sp_RIGHT) != 0) | ||
+ | dx = 0; | ||
+ | if ((i & sp_UP) == 0) | ||
+ | dy = -dy; | ||
+ | else if ((i & sp_DOWN) != 0) | ||
+ | dy = 0; | ||
+ | if (sp_KeyPressed(reset)) | ||
+ | | ||
+ | else | ||
+ | | ||
+ | if (sp_KeyPressed(cambioBorde)) | ||
+ | if (borde == 1) | ||
+ | { | ||
+ | borde = 2; | ||
+ | | ||
+ | } | ||
+ | | ||
+ | { | ||
+ | borde = 1; | ||
+ | | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | #asm | ||
+ | |||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | |||
+ | ._bicho1 | ||
+ | defb @00000011, @11111100 | ||
+ | defb @00000100, @11111000 | ||
+ | defb @00001000, @11110000 | ||
+ | defb @00001011, @11110000 | ||
+ | defb @00001011, @11110000 | ||
+ | defb @00001000, @11110000 | ||
+ | defb @00001000, @11110000 | ||
+ | defb @00000100, @11111000 | ||
+ | |||
+ | defb @00000011, @11111100 | ||
+ | defb @00001100, @11110011 | ||
+ | defb @00001100, @11110011 | ||
+ | defb @00011000, @11100111 | ||
+ | defb @00011000, @11100111 | ||
+ | defb @01111100, @10000011 | ||
+ | defb @01111100, @10000011 | ||
+ | defb @00000000, @11111111 | ||
+ | |||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | |||
+ | ._bicho2 | ||
+ | defb @11100000, @00011111 | ||
+ | defb @00010000, @00001111 | ||
+ | defb @00001000, @00000111 | ||
+ | defb @01101000, @00000111 | ||
+ | defb @01101000, @00000111 | ||
+ | defb @00001000, @00000111 | ||
+ | defb @10001000, @00000111 | ||
+ | defb @10010000, @00001111 | ||
+ | |||
+ | defb @11100000, @00011111 | ||
+ | defb @00011000, @11100111 | ||
+ | defb @00011000, @11100111 | ||
+ | defb @00001100, @11110011 | ||
+ | defb @00001100, @11110011 | ||
+ | defb @00111110, @11000001 | ||
+ | defb @00111110, @11000001 | ||
+ | defb @00000000, @11111111 | ||
+ | |||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | |||
+ | ._bicho3 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | |||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | |||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | |||
+ | #endasm | ||
+ | </ | ||
+ | |||
+ | Como se puede comprobar, tras crear el sprite del bicho, hacemos uso de la siguiente instrucción: | ||
+ | |||
+ | <code c> | ||
+ | sp_IterateSprChar(spriteBicho, | ||
+ | </ | ||
+ | |||
+ | Esto significa que vamos a usar una función llamada **addColour**, | ||
+ | |||
+ | <code c> | ||
+ | uchar n; | ||
+ | void addColour(struct sp_CS *cs) | ||
+ | { | ||
+ | if (n == 0) // Se rellena de arriba a abajo y de izquierda | ||
+ | | ||
+ | cs-> | ||
+ | else if (n == 1) | ||
+ | cs-> | ||
+ | else if (n == 2) | ||
+ | | ||
+ | else if (n == 3) | ||
+ | | ||
+ | else if (n == 4) | ||
+ | | ||
+ | | ||
+ | | ||
+ | if (n > 5) | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Justo antes se define una variable global llamada n, y que no será más que un contador que nos permitirá saber en cuál de las nueve llamadas a la función **addColour** nos encontramos. Ya dentro de dicho método se observa como su valor se incrementa de uno en uno en cada llamada. | ||
+ | |||
+ | Como hemos repetido varias veces, //la función **addColour** será llamada una vez por cada bloque 8x8 que forme nuestro sprite//, recibiendo como parámetro un struct de tipo //sp_CS// que nos va a permitir modificar diversas características de dicho bloque del sprite. Uno de los campos de ese struct es colour, que como su propio nombre indica, es el indicado para añadir color. Gracias al valor de n, podremos conocer en cuál de todos los bloques del sprite nos encontramos (empezando por el 0, los bloques están ordenados de arriba a abajo y de izquierda a derecha, por lo que en el caso de nuestro bicho, aun estando compuesto por 3x3 bloques, sólo nos interesará colorear aquellos para los que n vale 0,1,3 y 4, que son los que no están vacíos) y asignarle un color de tinta y papel modificando el valor del campo colour del //struct sp_CS//, tal como se puede observar en el código anterior. | ||
+ | |||
+ | Sólo deberemos colorear los bloques 0, 1, 3 y 4 de nuestro bicho, pues el bloque 2 se corresponde con el último de la primera columna (que está vacío), el bloque 5 con el último de la segunda columna (que también está vacío) y los bloques 6,7 y 8 con la última columna de todas, también vacía, y que se añadió para que no hubiera problemas al desplazar el sprite. En el caso de los bloques 2 y 5 lo más correcto hubiera sido utilizar el valor // | ||
+ | |||
+ | <code c> | ||
+ | extern uchar *sp_NullSprPtr; | ||
+ | #asm | ||
+ | LIB SPNullSprPtr | ||
+ | ._sp_NullSprPtr | ||
+ | #endasm | ||
+ | </ | ||
+ | |||
+ | evitará que esa columna vacía " | ||
+ | |||
+ | Y ya está, ya le hemos dado color a nuestro bicho (eso sí, una combinación bastante psicodélica). Cada vez que queramos hacer lo mismo con cualquier otro sprite, tan solo deberemos seguir la receta anterior, pues es algo mecánico. | ||
+ | |||
+ | {{ cursos: | ||
+ | |||
+ | |||
+ | ===== Un nuevo juego ===== | ||
+ | |||
+ | A continuación, | ||
+ | |||
+ | {{ cursos: | ||
+ | |||
+ | El código completo, que comentaremos a lo largo de esta sección (aunque no en detalle, sólo aquellas partes que difieran de lo visto hasta ahora o introduzcan conceptos nuevos), es el siguiente: | ||
+ | |||
+ | <code c> | ||
+ | #include < | ||
+ | #include < | ||
+ | #pragma output STACKPTR=61440 | ||
+ | |||
+ | #define NUM_ROCAS 8 | ||
+ | |||
+ | extern struct sp_Rect *sp_ClipStruct; | ||
+ | #asm | ||
+ | LIB SPCClipStruct | ||
+ | ._sp_ClipStruct | ||
+ | #endasm | ||
+ | |||
+ | extern uchar *sp_NullSprPtr; | ||
+ | #asm | ||
+ | LIB SPNullSprPtr | ||
+ | ._sp_NullSprPtr | ||
+ | #endasm | ||
+ | |||
+ | extern uchar roca1[]; | ||
+ | extern uchar roca2[]; | ||
+ | extern uchar roca3[]; | ||
+ | extern uchar banderin1[]; | ||
+ | extern uchar banderin2[]; | ||
+ | extern uchar skiCentrado1[]; | ||
+ | extern uchar skiCentrado2[]; | ||
+ | extern uchar skiIzquierda1[]; | ||
+ | extern uchar skiIzquierda2[]; | ||
+ | extern uchar skiDerecha1[]; | ||
+ | extern uchar skiDerecha2[]; | ||
+ | struct sp_UDK keys; | ||
+ | |||
+ | void *my_malloc(uint bytes) | ||
+ | { | ||
+ | | ||
+ | } | ||
+ | |||
+ | void *u_malloc = my_malloc; | ||
+ | void *u_free = sp_FreeBlock; | ||
+ | |||
+ | uchar n; | ||
+ | void addColourRoca(struct sp_CS *cs) | ||
+ | { | ||
+ | if (n >= 0 && n <= 5) | ||
+ | cs-> | ||
+ | else | ||
+ | | ||
+ | if (n > 5) | ||
+ | | ||
+ | n++; | ||
+ | | ||
+ | } | ||
+ | |||
+ | void addColourSki(struct sp_CS *cs) | ||
+ | { | ||
+ | if (n == 0) | ||
+ | cs-> | ||
+ | else if (n == 2) | ||
+ | cs-> | ||
+ | else | ||
+ | cs-> | ||
+ | if (n>2) | ||
+ | cs-> | ||
+ | n++; | ||
+ | return; | ||
+ | } | ||
+ | |||
+ | main() | ||
+ | { | ||
+ | char dx,dy,i | ||
+ | | ||
+ | | ||
+ | short int posicion = 0; | ||
+ | int roca = 0; | ||
+ | |||
+ | |||
+ | #asm | ||
+ | di | ||
+ | #endasm | ||
+ | sp_InitIM2(0xf1f1); | ||
+ | sp_CreateGenericISR(0xf1f1); | ||
+ | #asm | ||
+ | ei | ||
+ | #endasm | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | |||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | |||
+ | for (i=0; | ||
+ | { | ||
+ | n = 0; | ||
+ | spriteRoca[i] = sp_CreateSpr(sp_OR_SPRITE, | ||
+ | sp_AddColSpr(spriteRoca[i], | ||
+ | sp_AddColSpr(spriteRoca[i], | ||
+ | sp_IterateSprChar(spriteRoca[i], | ||
+ | sp_MoveSprAbs(spriteRoca[i], | ||
+ | } | ||
+ | |||
+ | n = 0; | ||
+ | | ||
+ | | ||
+ | | ||
+ | |||
+ | n = 0; | ||
+ | | ||
+ | | ||
+ | | ||
+ | |||
+ | n = 0; | ||
+ | | ||
+ | | ||
+ | | ||
+ | |||
+ | ski = spriteSkiCentrado; | ||
+ | |||
+ | | ||
+ | |||
+ | |||
+ | | ||
+ | | ||
+ | |||
+ | i = sp_JoyKeyboard(& | ||
+ | dx = 0; | ||
+ | dy = 0; | ||
+ | if ((i & sp_LEFT) == 0 && ski->col > 0) | ||
+ | { | ||
+ | if (posicion != -1) | ||
+ | { | ||
+ | sp_MoveSprAbs(spriteSkiIzquierda, | ||
+ | sp_MoveSprAbs(ski, | ||
+ | ski = spriteSkiIzquierda; | ||
+ | posicion = -1; | ||
+ | } | ||
+ | dx = -3; | ||
+ | } | ||
+ | else if ((i & sp_RIGHT) == 0 && ski->col < 30) | ||
+ | { | ||
+ | if (posicion != 1) | ||
+ | { | ||
+ | sp_MoveSprAbs(spriteSkiDerecha, | ||
+ | sp_MoveSprAbs(ski, | ||
+ | ski = spriteSkiDerecha; | ||
+ | posicion = 1; | ||
+ | } | ||
+ | dx = 3; | ||
+ | } | ||
+ | else | ||
+ | { | ||
+ | if (posicion != 0) | ||
+ | { | ||
+ | sp_MoveSprAbs(spriteSkiCentrado, | ||
+ | sp_MoveSprAbs(ski, | ||
+ | ski = spriteSkiCentrado; | ||
+ | posicion = 0; | ||
+ | } | ||
+ | } | ||
+ | if (dx != 0) sp_MoveSprRel(ski, | ||
+ | |||
+ | if (spriteRoca[roca]-> | ||
+ | { | ||
+ | dx = 0; | ||
+ | dy = -4; | ||
+ | sp_MoveSprRel(spriteRoca[roca], | ||
+ | } | ||
+ | else | ||
+ | if (rand()%100> | ||
+ | { | ||
+ | sp_MoveSprAbs(spriteRoca[roca], | ||
+ | } | ||
+ | roca ++; | ||
+ | if (roca >= NUM_ROCAS) | ||
+ | roca = 0; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | #asm | ||
+ | |||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | |||
+ | ._roca1 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000001, @11111110 | ||
+ | defb @00000011, @11111100 | ||
+ | defb @00000011, @11111100 | ||
+ | defb @00000111, @11111000 | ||
+ | |||
+ | defb @00001111, @11110000 | ||
+ | defb @00001111, @11110000 | ||
+ | defb @00011111, @11100000 | ||
+ | defb @00111111, @11000000 | ||
+ | defb @00111111, @11000000 | ||
+ | defb @00111110, @11000000 | ||
+ | defb @01111110, @10000000 | ||
+ | defb @01111110, @10000000 | ||
+ | |||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | |||
+ | ._roca2 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @01100000, @10011111 | ||
+ | defb @11110000, @00001111 | ||
+ | defb @11111000, @00000111 | ||
+ | defb @11111000, @00000111 | ||
+ | defb @10111000, @00000111 | ||
+ | |||
+ | defb @10111100, @00000011 | ||
+ | defb @10111100, @00000011 | ||
+ | defb @10111100, @00000011 | ||
+ | defb @01111110, @00000001 | ||
+ | defb @01111110, @00000001 | ||
+ | defb @11111110, @00000001 | ||
+ | defb @11111111, @00000000 | ||
+ | defb @11111111, @00000000 | ||
+ | |||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | |||
+ | ._roca3 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | |||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | |||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | |||
+ | ._skiCentrado1 | ||
+ | defb @00111110, @11000001 | ||
+ | defb @01101011, @10000000 | ||
+ | defb @00111110, @11000001 | ||
+ | defb @00011100, @11100011 | ||
+ | defb @00010100, @11101011 | ||
+ | defb @00100010, @11011101 | ||
+ | defb @00100010, @11011101 | ||
+ | defb @01000001, @10111110 | ||
+ | |||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | |||
+ | ._skiCentrado2 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | |||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | |||
+ | ._skiIzquierda1 | ||
+ | defb @00011111, @11100000 | ||
+ | defb @00110101, @11000000 | ||
+ | defb @00011111, @11100000 | ||
+ | defb @00001110, @11110001 | ||
+ | defb @00010010, @11101101 | ||
+ | defb @00100100, @11011011 | ||
+ | defb @01001000, @10110111 | ||
+ | defb @00000000, @11111111 | ||
+ | |||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | |||
+ | ._skiIzquierda2 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | |||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | |||
+ | ._skiDerecha1 | ||
+ | defb @11111000, @00000111 | ||
+ | defb @10101100, @00000011 | ||
+ | defb @11111000, @00000111 | ||
+ | defb @01110000, @10001111 | ||
+ | defb @01001000, @10110111 | ||
+ | defb @00100100, @11011011 | ||
+ | defb @00010010, @11101101 | ||
+ | defb @00000000, @11111111 | ||
+ | |||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | |||
+ | ._skiDerecha2 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | |||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | defb @00000000, @11111111 | ||
+ | |||
+ | #endasm | ||
+ | </ | ||
+ | |||
+ | Se han definido un total de cuatro sprites. El sprite de tipo //roca// (dividido en tres columnas denominadas //roca1, roca2// y //roca3//) será el que representará los obstáculos que encontrará nuestro intrépido esquiador en su descenso. Para el protagonista de nuestro juego se han definido tres sprites divididos cada uno de ellos en dos columnas: skiCentrado que será el que se mostrará cuando el esquiador esté descendiendo sin que lo movamos a izquierda o derecha, skiIzquierda que representa nuestro esquiador desplazándose hacia la izquierda, y skiDerecha que a su vez representa al mismo esquiador desplazándose a la derecha. | ||
+ | |||
+ | Como debemos reservar memoria para los sprites que vayamos a mostrar por pantalla, lo haremos para cada una de las tres posiciones del esquiador (de tal forma que mostraremos la adecuada según el movimiento del jugador) y un número fijo de rocas. Es probable que no todas las rocas sean visibles simultáneamente durante el juego, pero hacerlo de esta forma simplifica en gran medida el diseño, sin tener que hacer grandes esfuerzos para reservar o liberar memoria cuando sea necesario. En concreto, la constante NUM_ROCAS es la que vamos a usar para indicar el número de rocas que se van a crear. Se define un array llamado spriteRoca con tantas posiciones como las indicadas por la constante anteriormente mencionada, y en cada posición de dicho array se reserva memoria para un sprite de tipo roca que es coloreado con su correspondiente función addColour: | ||
+ | |||
+ | <code c> | ||
+ | for (i=0; | ||
+ | { | ||
+ | n = 0; | ||
+ | spriteRoca[i] = sp_CreateSpr(sp_OR_SPRITE, | ||
+ | sp_AddColSpr(spriteRoca[i], | ||
+ | sp_AddColSpr(spriteRoca[i], | ||
+ | sp_IterateSprChar(spriteRoca[i], | ||
+ | sp_MoveSprAbs(spriteRoca[i], | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Un par de comentarios sobre la definición de los sprites en este programa: como primer parámetro para los sprites de tipo roca en la función **sp_CreateSpr** se pasa el valor // | ||
+ | |||
+ | Una vez creados los sprites se utilizan las siguientes instrucciones: | ||
+ | |||
+ | <code c> | ||
+ | i = spriteSkiCentrado; | ||
+ | |||
+ | sp_MoveSprAbs(ski, | ||
+ | </ | ||
+ | |||
+ | El puntero **ski** apuntará en todo momento al sprite del esquiador que deba ser mostrado por pantalla. El esquiador comenzará mirando hacia abajo, ya que no se está moviendo ni a izquierda ni a derecha; por lo tanto, //ski// apuntará al sprite // | ||
+ | |||
+ | En el bucle principal iniciado por la sentencia while(1) y que se ejecutará de forma infinita, vemos como se resuelve el tema de la animación del protagonista, | ||
+ | |||
+ | <code c> | ||
+ | i = sp_JoyKeyboard(& | ||
+ | dx = 0; | ||
+ | dy = 0; | ||
+ | if ((i & sp_LEFT) == 0 && ski->col > 0) | ||
+ | { | ||
+ | if (posicion != -1) | ||
+ | { | ||
+ | sp_MoveSprAbs(spriteSkiIzquierda, | ||
+ | sp_MoveSprAbs(ski, | ||
+ | ski = spriteSkiIzquierda; | ||
+ | posicion = -1; | ||
+ | } | ||
+ | dx = -3; | ||
+ | } | ||
+ | else if ((i & sp_RIGHT) == 0 && ski->col < 30) | ||
+ | { | ||
+ | if (posicion != 1) | ||
+ | { | ||
+ | sp_MoveSprAbs(spriteSkiDerecha, | ||
+ | sp_MoveSprAbs(ski, | ||
+ | ski = spriteSkiDerecha; | ||
+ | posicion = 1; | ||
+ | } | ||
+ | dx = 3; | ||
+ | } | ||
+ | else | ||
+ | { | ||
+ | if (posicion != 0) | ||
+ | { | ||
+ | sp_MoveSprAbs(spriteSkiCentrado, | ||
+ | sp_MoveSprAbs(ski, | ||
+ | ski = spriteSkiCentrado; | ||
+ | posicion = 0; | ||
+ | } | ||
+ | } | ||
+ | if (dx != 0) sp_MoveSprRel(ski, | ||
+ | </ | ||
+ | |||
+ | Cada vez que el esquiador cambia de posición, se debe hacer apuntar a //ski// hacia el sprite adecuado. Esto sólo se debe hacer en la primera iteración en la que estemos moviéndonos en esa dirección. Para ello se observa que se utiliza una variable posicion, inicializada a cero, y que valdrá precisamente 0 si el sprite a mostrar por pantalla debe ser // | ||
+ | |||
+ | Veámoslo con un ejemplo. Supongamos que el esquiador se está deslizando ladera abajo, sin que el jugador lo mueva a izquierda o derecha. En este caso, //ski// apunta a // | ||
+ | |||
+ | * Se mueve // | ||
+ | * A continuación, | ||
+ | * La variable //ski// apunta a // | ||
+ | * Se cambia el valor de posicion a 1, indicando que ya hemos estado al menos una iteración desplazándonos hacia la derecha y que no es necesario repetir todas estas operaciones en el caso en el que sigamos moviéndonos en esta dirección. | ||
+ | |||
+ | Sólo podremos desplazarnos hacia la izquierda o la derecha siempre que nos encontremos dentro de los límites de la pantalla. Esto se controla de la siguiente forma: | ||
+ | |||
+ | <code c> | ||
+ | if ((i & sp_LEFT) == 0 && ski->col > 0) | ||
+ | |||
+ | else if ((i & sp_RIGHT) == 0 && ski->col < 30) | ||
+ | </ | ||
+ | |||
+ | Con respecto a las rocas, moveremos tan solo una en cada iteración del bucle principal. Esto no es más que una medida preliminar para conseguir un mínimo de velocidad y algo de sincronización, | ||
+ | |||
+ | <code c> | ||
+ | if (spriteRoca[roca]-> | ||
+ | { | ||
+ | dx = 0; | ||
+ | dy = -4; | ||
+ | sp_MoveSprRel(spriteRoca[roca], | ||
+ | } | ||
+ | else | ||
+ | if (rand()%100> | ||
+ | { | ||
+ | sp_MoveSprAbs(spriteRoca[roca], | ||
+ | } | ||
+ | roca ++; | ||
+ | if (roca >= NUM_ROCAS) | ||
+ | roca = 0; | ||
+ | </ | ||
+ | |||
+ | Cada roca se desplazará hacia arriba en la pantalla usando un valor de desplazamiento dy = -4, hasta llegar a un valor de -10 en su coordenada y. En ese momento, la roca ya habrá desaparecido de la pantalla por su parte superior. Si una roca está fuera de la pantalla, volveremos a sacarla por debajo de nuevo en una posición x al azar (como si fuera otra roca distinta) con una probabilidad del 98% (para que una roca que ha salido por la parte superior de la pantalla no vuelva a aparecer inmediatamente por la parte inferior y que efectivamente parezca una roca diferente). Se podría modificar el valor de la constante // | ||
+ | |||
+ | Una vez que compilamos y ejecutamos nuestro juego, nos encontramos con tres problemas, que trataremos de resolver en artículos sucesivos: | ||
+ | |||
+ | * No hay colisiones. Nuestro esquiador parece un fantasma, pues puede atravesar las rocas sin que éstas le afecten. Eso es porque no hemos establecido un control de colisiones. | ||
+ | * No hay sincronización. Esto quiere decir que la velocidad del juego es diferente según el número de rocas que se estén mostrando en determinado momento por la pantalla. Haciendo uso de las interrupciones podremos conseguir que haya el número de rocas que haya, la velocidad de descenso se mantenga constante. | ||
+ | * Colour clash. Cuando nuestro esquiador y las rocas entran en contacto, se produce un choque de atributos bastante desagradable (los colores de los sprites parecen " | ||
+ | |||
+ | Por último, un apunte sobre la liberación de memoria. Como hemos visto, cada vez que queremos mostrar un sprite por pantalla, debemos reservar memoria para el mismo. En el caso en el que un sprite no vaya a ser mostrado nunca más, lo más adecuado es liberar la memoria correspondiente, | ||
+ | |||
+ | |||
+ | ===== Y en el próximo número... ===== | ||
+ | |||
+ | ¡La programación de nuestro juego ha comenzado! Sin embargo, nos encontramos con varios problemas, tal como se ha comentado anteriormente; | ||
+ | |||
+ | ===== Enlaces ===== | ||
+ | |||
+ | |||
+ | * [[https:// | ||
+ | |||
+ |