Diferencias

Muestra las diferencias entre dos versiones de la página.

Enlace a la vista de comparación

Ambos lados, revisión anterior Revisión previa
Próxima revisión
Revisión previa
cursos:z88dk:sprites2 [10-08-2007 09:57]
sromero
cursos:z88dk:sprites2 [24-02-2020 20:24] (actual)
falvarez
Línea 1: Línea 1:
 +Publicado originalmente en [[https://magazinezx.speccy.org/12/z88dk.html|MagazineZX número 12]] (septiembre 2005)
 +
 +====== Curso de Z88DK: Sprites (II) ======
  
 ===== ¡Mis Sprites se mueven! ===== ===== ¡Mis Sprites se mueven! =====
Línea 86: Línea 89:
  
 {{ cursos:z88dk:z88dk7_3.png |Los sprites mostrándose en la pantalla de nuestro Spectrum}} {{ cursos:z88dk:z88dk7_3.png |Los sprites mostrándose en la pantalla de nuestro Spectrum}}
 +
  
  
Línea 95: Línea 99:
 Para conseguir esto último, es decir, que se nos muestre un sprite distinto del coche según se esté moviendo hacia arriba, hacia abajo, etc., debemos añadir un par de cambios al archivo coches.h. Lo primero que vamos a hacer es almacenar todos los sprites en un único array de arrays de chars (es decir, en un único array de sprites). Esto lo hacemos colocando después de la definición de los diferentes sprites en coches.h una línea como la siguiente: Para conseguir esto último, es decir, que se nos muestre un sprite distinto del coche según se esté moviendo hacia arriba, hacia abajo, etc., debemos añadir un par de cambios al archivo coches.h. Lo primero que vamos a hacer es almacenar todos los sprites en un único array de arrays de chars (es decir, en un único array de sprites). Esto lo hacemos colocando después de la definición de los diferentes sprites en coches.h una línea como la siguiente:
  
 +<code c>
 char *sprites[9] = { sprite0 , sprite1 , sprite2 , sprite3 , sprite4 , sprite5 , char *sprites[9] = { sprite0 , sprite1 , sprite2 , sprite3 , sprite4 , sprite5 ,
     sprite6 , sprite7 , sprite8 };     sprite6 , sprite7 , sprite8 };
 +</code>
  
 De tal forma que podremos acceder al sprite i utilizando, por ejemplo, sprites[i] en lugar de spritei, lo cual nos va a ser de mucha utilidad. Justo después de esta línea, introducimos las dos líneas siguientes en coches.h: De tal forma que podremos acceder al sprite i utilizando, por ejemplo, sprites[i] en lugar de spritei, lo cual nos va a ser de mucha utilidad. Justo después de esta línea, introducimos las dos líneas siguientes en coches.h:
  
 +<code c>
 int izquierda[] = {4,6,7,5,1,0,2,3}; int izquierda[] = {4,6,7,5,1,0,2,3};
 int derecha[] = {5,4,6,7,0,3,1,2}; int derecha[] = {5,4,6,7,0,3,1,2};
 +</code>
  
 Estos dos arrays los utilizaremos para saber, cada vez que giramos, cuál es el sprite que debemos dibujar en la pantalla. Si los sprites están numerados según la primera figura de este artículo, y ahora mismo se nos muestra en la pantalla el sprite 0, si giramos a la izquierda el que se debería mostrar es el 4. Si volvemos a girar a la izquierda, el que debería dibujarse entonces en la pantalla es el 1, etc. Si por el contrario, estamos mostrando el sprite 0 en la pantalla y giramos a la derecha, se nos debería mostrar el sprite 5. Si volvemos a girar a la derecha, se nos debería mostrar el sprite 3, etc. Estos dos arrays los utilizaremos para saber, cada vez que giramos, cuál es el sprite que debemos dibujar en la pantalla. Si los sprites están numerados según la primera figura de este artículo, y ahora mismo se nos muestra en la pantalla el sprite 0, si giramos a la izquierda el que se debería mostrar es el 4. Si volvemos a girar a la izquierda, el que debería dibujarse entonces en la pantalla es el 1, etc. Si por el contrario, estamos mostrando el sprite 0 en la pantalla y giramos a la derecha, se nos debería mostrar el sprite 5. Si volvemos a girar a la derecha, se nos debería mostrar el sprite 3, etc.
Línea 109: Línea 117:
 Habiendo hecho estas dos modificaciones, ya podemos incluir aquí el código de un programa que llamaremos movimiento.c, que nos pondrá a los mandos de un coche que se mostrará en la pantalla, el cual podremos mover hacia donde queramos, sin ninguna restricción. Habiendo hecho estas dos modificaciones, ya podemos incluir aquí el código de un programa que llamaremos movimiento.c, que nos pondrá a los mandos de un coche que se mostrará en la pantalla, el cual podremos mover hacia donde queramos, sin ninguna restricción.
  
 +<code c>
 #include "stdio.h" #include "stdio.h"
 #include "ctype.h" #include "ctype.h"
Línea 139: Línea 148:
         }         }
 } }
 +</code>
  
 De momento vamos a comenzar con los giros, y ya surcaremos después la pantalla a toda velocidad. El código anterior nos dibuja el coche en una zona cercana al centro de la pantalla, y nos permite girarlo hacia la izquierda y hacia la derecha empleando las teclas o y p respectivamente. Explicamos el código y más adelante indicamos un problema que se muestra durante la ejecuciñón y cómo solucionarlo. De momento vamos a comenzar con los giros, y ya surcaremos después la pantalla a toda velocidad. El código anterior nos dibuja el coche en una zona cercana al centro de la pantalla, y nos permite girarlo hacia la izquierda y hacia la derecha empleando las teclas o y p respectivamente. Explicamos el código y más adelante indicamos un problema que se muestra durante la ejecuciñón y cómo solucionarlo.
Línea 158: Línea 168:
 Queremos que pulsando la tecla 'q' el coche vaya acelerando hasta una velocidad máxima (y por lo tanto, que se vaya moviendo conforme a esa velocidad) y que al pulsar la tecla 'a', el coche vaya frenando hasta detenerse. A continuación vemos como lo hemos resuelto, en el siguiente programa, que sustituirá a nuestro anterior movimiento.c (el código marcado como "Nuevo" es el añadido): Queremos que pulsando la tecla 'q' el coche vaya acelerando hasta una velocidad máxima (y por lo tanto, que se vaya moviendo conforme a esa velocidad) y que al pulsar la tecla 'a', el coche vaya frenando hasta detenerse. A continuación vemos como lo hemos resuelto, en el siguiente programa, que sustituirá a nuestro anterior movimiento.c (el código marcado como "Nuevo" es el añadido):
  
 +<code c>
 #include "stdio.h" #include "stdio.h"
 #include "ctype.h" #include "ctype.h"
Línea 163: Línea 174:
 #include "coches.h" #include "coches.h"
  
 +// Nuevo
 #define CICLOS_BASE 300; #define CICLOS_BASE 300;
  
Línea 171: Línea 183:
         int posicion = 0;         int posicion = 0;
  
-        int velocidad = 0; +        int velocidad = 0;            // nuevo 
-        int ciclos = CICLOS_BASE;+        int ciclos = CICLOS_BASE;     // nuevo
  
         putsprite(spr_xor,x,y,sprites[0]);         putsprite(spr_xor,x,y,sprites[0]);
Línea 180: Línea 192:
                 switch(toupper(getk()))                 switch(toupper(getk()))
                 {                 {
 +                        // nuevo (Principio)
                         case 'Q':                         case 'Q':
                                 if (velocidad < 50)                                 if (velocidad < 50)
Línea 192: Línea 205:
                                }                                }
                                 break;                                 break;
 +                        // nuevo (Fin)
                         case 'O':                         case 'O':
                                 putsprite(spr_xor,x,y,sprites[posicion]);                                 putsprite(spr_xor,x,y,sprites[posicion]);
Línea 204: Línea 218:
                 }                 }
  
 +                // nuevo (Principio)
                 if (velocidad > 0)                 if (velocidad > 0)
                 {                 {
Línea 246: Línea 261:
                 }                 }
         }         }
 +        // nuevo (Fin)
 } }
 +</code>
  
-Lo más evidente es que necesitaremos una variable, en este caso llamada velocidad, que nos permita almacenar la velocidad del coche en un momento dado. Es importante tener en cuenta que en un principio el coche estará parado, por lo que esta velocidad valdrá cero. Hemos añadido también código que hará que nuestra velocidad aumente o disminuya, hasta una velocidad máxima o mínima, al pulsar las teclas 'q' y 'a', respectivamente (este código es el que se ha añadido dentro del switch).+Lo más evidente es que necesitaremos una variable, en este caso llamada //velocidad//, que nos permita almacenar la velocidad del coche en un momento dado. Es importante tener en cuenta que en un principio el coche estará parado, por lo que esta velocidad valdrá cero. Hemos añadido también código que hará que nuestra velocidad aumente o disminuya, hasta una velocidad máxima o mínima, al pulsar las teclas 'q' y 'a', respectivamente (este código es el que se ha añadido dentro del switch).
  
 Lo que a lo mejor queda un poco más esotérico es ver cómo hacemos que el coche, una vez que adquiere velocidad, pueda moverse. La parte del código encargada de esto es la que se encuentra al final. Este código, como es obvio, solo se ejecutará si el coche tiene velocidad. El coche se moverá cuando una variable, llamada ciclos, y a la que se le va restando el valor de la velocidad en cada iteración del bucle principal, llegue a cero. Evidentemente, cuanta mayor sea la velocidad, más rápido llegará ciclos a 0 y cada menos iteraciones del bucle principal se moverá el coche. Lo que a lo mejor queda un poco más esotérico es ver cómo hacemos que el coche, una vez que adquiere velocidad, pueda moverse. La parte del código encargada de esto es la que se encuentra al final. Este código, como es obvio, solo se ejecutará si el coche tiene velocidad. El coche se moverá cuando una variable, llamada ciclos, y a la que se le va restando el valor de la velocidad en cada iteración del bucle principal, llegue a cero. Evidentemente, cuanta mayor sea la velocidad, más rápido llegará ciclos a 0 y cada menos iteraciones del bucle principal se moverá el coche.
Línea 260: Línea 277:
 Las variables del sistema se podrían entender como determinadas direcciones de memoría que modifican el comportamiento del sistema según su valor (más información en la Microhobby especial nº2). En nuestro caso concreto, las variables del sistema que vamos a modificar son REPDEL y REPPER, correspondientes a las direcciones de memoria 23561 y 23562. La primera de ellas indica el tiempo en cincuentavos de segundo que se debe tener pulsada una tecla para que esta se comience a repetir, y la segunda indica el tiempo en cincuentavos de segundo que tarda en producirse esta repetición una vez que se comienza. Si le damos un valor de 1 a estas variables, conseguiremos una respuesta dle teclado rápida, y nos desharemos del efecto tan fastidioso que hemos comentado antes. Las variables del sistema se podrían entender como determinadas direcciones de memoría que modifican el comportamiento del sistema según su valor (más información en la Microhobby especial nº2). En nuestro caso concreto, las variables del sistema que vamos a modificar son REPDEL y REPPER, correspondientes a las direcciones de memoria 23561 y 23562. La primera de ellas indica el tiempo en cincuentavos de segundo que se debe tener pulsada una tecla para que esta se comience a repetir, y la segunda indica el tiempo en cincuentavos de segundo que tarda en producirse esta repetición una vez que se comienza. Si le damos un valor de 1 a estas variables, conseguiremos una respuesta dle teclado rápida, y nos desharemos del efecto tan fastidioso que hemos comentado antes.
  
-En el siguiente código se muestran los cambios que deberíamos realizar al comienzo del programa movimiento.c:+En el siguiente código se muestran los cambios que deberíamos realizar al comienzo del programa **movimiento.c**:
  
 +<code c>
 #include "stdio.h" #include "stdio.h"
 #include "ctype.h" #include "ctype.h"
Línea 275: Línea 293:
         int posicion = 0;         int posicion = 0;
  
-        char *puntero1 = (char *) 23561; +        char *puntero1 = (char *) 23561;       // nuevo 
-        char *puntero2 = (char *) 23562; +        char *puntero2 = (char *) 23562;       // nuevo
  
         int velocidad = 0;         int velocidad = 0;
Línea 286: Línea 303:
         while(1)         while(1)
         {         {
-                *puntero1 = 1; +                *puntero1 = 1;                 // nuevo 
-                *puntero2 = 1;+                *puntero2 = 1;                 // nuevo
                 switch(toupper(getk()))                 switch(toupper(getk()))
                 {                 {
 +</code>
  
 Al mejorar la respuesta del teclado nos ha surgido un nuevo problema... ¡el coche gira demasiado rápido!. Al mejorar la respuesta del teclado nos ha surgido un nuevo problema... ¡el coche gira demasiado rápido!.
Línea 295: Línea 313:
 Será conveniente añadir un contador para que el coche no gire nada más pulsar la tecla correspondiente; mejor que gire cuando la tecle lleve un rato pulsada. A continuación mostramos el código que deberíamos añadir: Será conveniente añadir un contador para que el coche no gire nada más pulsar la tecla correspondiente; mejor que gire cuando la tecle lleve un rato pulsada. A continuación mostramos el código que deberíamos añadir:
  
-        int girando = 0; +<code c> 
-        int contador_izquierda = 0; +        int girando = 0;                       // nuevo 
-        int contador_derecha = 0;+        int contador_izquierda = 0;            // nuevo 
 +        int contador_derecha = 0;              // nuevo
         int velocidad = 0;         int velocidad = 0;
         int ciclos = CICLOS_BASE;         int ciclos = CICLOS_BASE;
Línea 325: Línea 344:
                                 break;                                 break;
                         case 'O':                         case 'O':
 +                                // nuevo bloque, hasta el if (incluído)
                                 contador_derecha = 0;                                 contador_derecha = 0;
                                 contador_izquierda = contador_izquierda + 1;                                 contador_izquierda = contador_izquierda + 1;
                                 girando = 1;                                 girando = 1;
-                                if (contador_izquierda == 3)+                                if (contador_izquierda == 3)  
                                 {                                 {
                                         putsprite(spr_xor,x,y,sprites[posicion]);                                         putsprite(spr_xor,x,y,sprites[posicion]);
                                         posicion = izquierda[posicion];                                         posicion = izquierda[posicion];
                                         putsprite(spr_xor,x,y,sprites[posicion]);                                         putsprite(spr_xor,x,y,sprites[posicion]);
-                                        contador_izquierda = 0;+                                        contador_izquierda = 0;          // nuevo
                                 }                                 }
                                 break;                                 break;
                        case 'P':                        case 'P':
 +                                // nuevo bloque, hasta el if (incluído)
                                 contador_izquierda = 0;                                 contador_izquierda = 0;
                                 contador_derecha = contador_derecha + 1;                                 contador_derecha = contador_derecha + 1;
Línea 345: Línea 366:
                                         posicion = derecha[posicion];                                         posicion = derecha[posicion];
                                         putsprite(spr_xor,x,y,sprites[posicion]);                                         putsprite(spr_xor,x,y,sprites[posicion]);
-                                        contador_derecha = 0; +                                        contador_derecha = 0;           // nuevo  
-                                 +                                
-                                 break;+                                break;
                 }                 }
  
-                if (girando == 0)+                // nuevo (Principio) 
 +                if (girando == 0)     
                 {                 {
                         contador_izquierda = 0;                         contador_izquierda = 0;
                         contador_derecha = 0;                         contador_derecha = 0;
                 }                 }
 +                // nuevo (Fin)
  
                 if (velocidad > 0)                 if (velocidad > 0)
                 {                 {
 +</code>
  
-Nos vamos a basar en tres nuevas variables, girando, contador_izquierda y contador_derecha. Las dos últimas son las que nos van a indicar cuándo hacer el giro. Cada vez que le demos a la tecla de giro a la izquierda, aumentará el valor de contador_izquierda, y cada vez que le demos a la tecla de giro a la derecha, aumentará el valor de contador_derecha. Cuando alguna de ellas valga 3, giraremos a la izquierda o a la derecha, respectivamente.+Nos vamos a basar en tres nuevas variables, //girando, contador_izquierda// //contador_derecha//. Las dos últimas son las que nos van a indicar cuándo hacer el giro. Cada vez que le demos a la tecla de giro a la izquierda, aumentará el valor de contador_izquierda, y cada vez que le demos a la tecla de giro a la derecha, aumentará el valor de contador_derecha. Cuando alguna de ellas valga 3, giraremos a la izquierda o a la derecha, respectivamente.
  
 Una medida que tomamos es que al girar hacia la izquierda, ponemos a cero la variable contador_derecha, que nos dice cuanto tiempo hemos estado girando a la derecha, y viceversa, cuando giramos a la derecha, ponemos a cero la variable contador_izquierda, que nos dice cuánto hemos girado hasta la izquierda hasta el momento. Así evitamos que, en el caso de haber estado girando hacia la izquierda durante un tiempo, por ejemplo, empecemos a girar a la derecha, y que tan solo haga falta rozar la tecla de giro izquierda para volver a girar a la izquierda, lo cual no es demasiado real. Una medida que tomamos es que al girar hacia la izquierda, ponemos a cero la variable contador_derecha, que nos dice cuanto tiempo hemos estado girando a la derecha, y viceversa, cuando giramos a la derecha, ponemos a cero la variable contador_izquierda, que nos dice cuánto hemos girado hasta la izquierda hasta el momento. Así evitamos que, en el caso de haber estado girando hacia la izquierda durante un tiempo, por ejemplo, empecemos a girar a la derecha, y que tan solo haga falta rozar la tecla de giro izquierda para volver a girar a la izquierda, lo cual no es demasiado real.
Línea 372: Línea 395:
 La instrucción en ensamblador que detiene la ejecución hasta que se produce una interrupción es HALT. Y en z88dk, ejecutar una instrucción en ensamblador en cualquier momento es tan sencillo como hacer uso de la función asm, que recibe como parámetro una cadena conteniendo la instrucción que deseamos ejecutar. Por lo tanto, resolver de una vez por todas nuestros problemas de movimiento es tan simple como colocar la instrucción asm("HALT") en los lugares adecuados. A continuación se muestra todo el código de movimiento.c tal como quedaría después de los cambios. La instrucción en ensamblador que detiene la ejecución hasta que se produce una interrupción es HALT. Y en z88dk, ejecutar una instrucción en ensamblador en cualquier momento es tan sencillo como hacer uso de la función asm, que recibe como parámetro una cadena conteniendo la instrucción que deseamos ejecutar. Por lo tanto, resolver de una vez por todas nuestros problemas de movimiento es tan simple como colocar la instrucción asm("HALT") en los lugares adecuados. A continuación se muestra todo el código de movimiento.c tal como quedaría después de los cambios.
  
 +<code c>
 #include "stdio.h" #include "stdio.h"
 #include "ctype.h" #include "ctype.h"
Línea 401: Línea 425:
         *puntero1 = 1;         *puntero1 = 1;
         *puntero2 = 1;         *puntero2 = 1;
-        asm("halt");+        asm("halt");        // nuevo
  
         girando = 0;         girando = 0;
Línea 425: Línea 449:
                 if (contador_izquierda == 3)                 if (contador_izquierda == 3)
                 {                 {
-                    asm("halt");+                    asm("halt");       // nuevo
                     putsprite(spr_xor,x,y,sprites[posicion]);                     putsprite(spr_xor,x,y,sprites[posicion]);
                     posicion = izquierda[posicion];                     posicion = izquierda[posicion];
Línea 434: Línea 458:
             case 'P':             case 'P':
                 contador_izquierda = 0;                 contador_izquierda = 0;
-                                contador_derecha = contador_derecha + 1; +                contador_derecha = contador_derecha + 1; 
-                                girando = 1; +                girando = 1; 
-                                if (contador_derecha == 3) +                if (contador_derecha == 3) 
-                                +                
-                    asm("halt"); +                    asm("halt");       // nuevo 
-                                    putsprite(spr_xor,x,y,sprites[posicion]); +                    putsprite(spr_xor,x,y,sprites[posicion]); 
-                                    posicion = derecha[posicion]; +                    posicion = derecha[posicion]; 
-                                    putsprite(spr_xor,x,y,sprites[posicion]); +                    putsprite(spr_xor,x,y,sprites[posicion]); 
-                                        contador_derecha = 0; +                    contador_derecha = 0; 
-                                 +                 
-                                 break; +                break; 
-        }+            }
  
-                if (girando == 0)+            if (girando == 0)
             {             {
                 contador_izquierda = 0;                 contador_izquierda = 0;
                 contador_derecha = 0;                 contador_derecha = 0;
-        }+            }
  
  
Línea 460: Línea 484:
             {             {
                 ciclos = CICLOS_BASE;                 ciclos = CICLOS_BASE;
-                asm("halt");+                asm("halt");       // nuevo
                 putsprite(spr_xor,x,y,sprites[posicion]);                 putsprite(spr_xor,x,y,sprites[posicion]);
                 switch(posicion)                 switch(posicion)
Línea 498: Línea 522:
     }     }
 } }
 +</code>
  
-Como se puede comprobar, se ha incluido un halt antes de la lectura de teclado, para detener el programa hasta que se pulse una tecla, y después se ha incluido un halt antes de borrar y volver a dibujar el sprite, para esperar el refresco de la pantalla. Como consecuencia, el coche irá más lento, es por ello que también hemos modificado el valor de CICLOS_BASE, la velocidad máxima, y el incremento y decremento de la velocidad. ¿Y os habeis fijado? Gracias a que hemos sincronizado el movimiento del coche con el refresco de la pantalla... ¡este ha dejado de parpadear al moverse!+Como se puede comprobar, se ha incluido un **halt** antes de la lectura de teclado, para detener el programa hasta que se pulse una tecla, y después se ha incluido un halt antes de borrar y volver a dibujar el sprite, para esperar el refresco de la pantalla. Como consecuencia, el coche irá más lento, es por ello que también hemos modificado el valor de CICLOS_BASE, la velocidad máxima, y el incremento y decremento de la velocidad. ¿Y os habeis fijado? Gracias a que hemos sincronizado el movimiento del coche con el refresco de la pantalla... ¡este ha dejado de parpadear al moverse!
  
 Por último, una cosa curiosa: si mientras movemos el coche pasamos por encima de donde pone Bytes: movimiento (correspondiente a la carga desde cinta) veremos como el borrado y la escritura del sprite del coche no afecta en lo mas mínimo a los píxeles que forman parte de ese texto; esto es sin duda otra de las grandes ventajas de usar el modo de dibujado de sprites or exclusiva. Por último, una cosa curiosa: si mientras movemos el coche pasamos por encima de donde pone Bytes: movimiento (correspondiente a la carga desde cinta) veremos como el borrado y la escritura del sprite del coche no afecta en lo mas mínimo a los píxeles que forman parte de ese texto; esto es sin duda otra de las grandes ventajas de usar el modo de dibujado de sprites or exclusiva.
  
-Y ahora, pongamos el coche en una pista+ 
 +===== Y ahora, pongamos el coche en una pista ===== 
  
 Por último vamos a dibujar una pista de neumáticos para limitar un poco el movimiento de nuestro bólido. Vamos además a hacerlo de tal forma que sea muy fácil modificar el trazado, y así la diversión se multiplique durante meses. Si recordamos, el último de los sprites que habíamos definido era el correspondiente a un neumático. Este sprite, com todos los anteriores, tiene un tamaño de 10x10 (quizá un poco grande, para hacer circuitos más complicados quizas no hubiera estado mal utilizar sprites de neumáticos más pequeños). Por último vamos a dibujar una pista de neumáticos para limitar un poco el movimiento de nuestro bólido. Vamos además a hacerlo de tal forma que sea muy fácil modificar el trazado, y así la diversión se multiplique durante meses. Si recordamos, el último de los sprites que habíamos definido era el correspondiente a un neumático. Este sprite, com todos los anteriores, tiene un tamaño de 10x10 (quizá un poco grande, para hacer circuitos más complicados quizas no hubiera estado mal utilizar sprites de neumáticos más pequeños).
Línea 509: Línea 536:
 Dentro de coches.h es donde definiremos el trazado de la pista. Si consideramos la pantalla como un array de 18x24 casillas de tamaño 10x10 (el mismo que los neumáticos), podemos indicar el recorrido de la pista creando un array, donde colocaremos ceros en aquellas casillas donde no vaya a haber neumático, y unos en las casillas en las que sí. Al principio de coches.h definimos unas constantes para el tamaño del circuito: Dentro de coches.h es donde definiremos el trazado de la pista. Si consideramos la pantalla como un array de 18x24 casillas de tamaño 10x10 (el mismo que los neumáticos), podemos indicar el recorrido de la pista creando un array, donde colocaremos ceros en aquellas casillas donde no vaya a haber neumático, y unos en las casillas en las que sí. Al principio de coches.h definimos unas constantes para el tamaño del circuito:
  
 +<code c>
 #define ALTURA_CIRCUITO 18 #define ALTURA_CIRCUITO 18
 #define ANCHURA_CIRCUITO 24 #define ANCHURA_CIRCUITO 24
 +</code>
  
 y al final del mismo archivo incluimos el siguiente array: y al final del mismo archivo incluimos el siguiente array:
  
 +<code c>
 short circuito1[] =  { 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, short circuito1[] =  { 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
     0, 0, 0, 0, 0, 0, 0 };     0, 0, 0, 0, 0, 0, 0 };
Línea 555: Línea 585:
     circuito12, circuito13, circuito14, circuito15, circuito16, circuito17,     circuito12, circuito13, circuito14, circuito15, circuito16, circuito17,
     circuito18};     circuito18};
 +</code>
  
-Con un poco de imaginación podemos vislumbrar en ese array un circuito cerrado en forma de O. Si ahora creamos un fichero llamado juego.c, que contenga el mismo código que movimiento.c, pero añadiéndole el que aparece en color rojo a continuación, podremos por fin ver nuestro circuito en la pantalla, tal como se ve en la siguiente imagen:+Con un poco de imaginación podemos vislumbrar en ese array un circuito cerrado en forma de O. Si ahora creamos un fichero llamado **juego.c**, que contenga el mismo código que movimiento.c, pero añadiéndole el que aparece en color rojo a continuación, podremos por fin ver nuestro circuito en la pantalla, tal como se ve en la siguiente imagen:
  
 +<codec>
 void main(void) void main(void)
 { {
Línea 563: Línea 595:
         int y = 140;         int y = 140;
         int posicion = 0;         int posicion = 0;
-        short int i+        short int ij;         // nuevo
-        short int j;+
  
         char *puntero1 = (char *) 23561;         char *puntero1 = (char *) 23561;
Línea 575: Línea 606:
         int ciclos = CICLOS_BASE;         int ciclos = CICLOS_BASE;
  
 +        // nuevo (Principio)
         for (i=0;i<30;i++)         for (i=0;i<30;i++)
                 printf("\n");                 printf("\n");
  
-        for (i=0;i +        for (i=0;i<ALTURA_CIRCUITO;i++) 
- +                for (j=0;j<ANCHURA_CIRCUITO;j++) 
-        putsprite(spr_xor,x,y,sprites[0]);+                        if (circuito[i][j] == 1) 
 +                                putsprite(spr_xor,j*10+1,i*10+1,sprites[8]); 
 +        // nuevo (Fin)
  
         while(1)         while(1)
Línea 587: Línea 621:
                 *puntero2 = 1;                 *puntero2 = 1;
                 asm("halt");                 asm("halt");
 +</code>
 +
  
-Figura 4. Nuestro coche dispuesto a ser el rey de la pista +{{ cursos:z88dk:z88dk7_4.png |Nuestro coche dispuesto a ser el rey de la pista}}
-Figura 4. Nuestro coche dispuesto a ser el rey de la pista+
  
 Hay que tener en cuenta que hemos cambiado el valor inicial de la coordenada y del coche para que éste quede dentro de la pista. También hemos creado dos variables, i y j que nos van a servir de contadores en un par de bucles. Hay que tener en cuenta que hemos cambiado el valor inicial de la coordenada y del coche para que éste quede dentro de la pista. También hemos creado dos variables, i y j que nos van a servir de contadores en un par de bucles.
Línea 926: Línea 961:
  
  
-    * [[http://www.speccy.org/magazinezx/revistas/12/src/z88dk_coches.zip|Código fuente de los ejemplos]]+    * [[https://magazinezx.speccy.org/12/src/z88dk_coches.zip|Código fuente de los ejemplos]]