26 septiembre 2014

Un mini-juego en BASIC de Amstrad CPC (3: emuladores, colores, while, teclado)

11. Programar desde un ordenador moderno

Si estás usando un emulador, existen opciones más cómodas que teclear directamente desde el propio emulador: puedes usar un editor más moderno, como Notepad++ o Geany, para teclear el programa y modificarlo, y luego llevarlo al emulador.:
  • Para WinApe puedes "copiar" el programa desde el editor y "pegarlo" en el emulador empleando la opción "Paste" del menú "File". Verás como el programa se va "tecleando" en el menulador poco a poco delante de tus ojos. Si has cambiado sólo una línea, puedes "copiar y pegar" sólo esa línea. El camino contrario también es posible: si quieres llevar tu programa desde el emulador al "mundo exterior", puedes entrar al menú "Settings", opción "Other" y asegurarte de que la impresora se está redirigiendo a un fichero. A partir de ese momento, si tecleas "LIST #8" (la almohadilla está en Mayúsculas+3), el contenido de tu programa se volcará a ese fichero.
  • Si utilizas CPCE, hay una alternativa aún más rápida para introducir todo el programa: puedes guardar el programa desde el editor con un nombre como "1.bas", entrar a CPCE, escoger la opción "Tape bypass" del menú "Options" para que las operaciones de cinta se redirijan al disco duro de tu ordenador anfitrión, luego teclear |TAPE (la barra vertical se consigue pulsando mayúsculas y la tecla que está a la derecha de la P) y finalmente LOAD". Aparecerá una ventana de diálogo que te permitirá escoger qué programa cargar (ése que habías guardado como "1.bas"). Incluso podríamos guardar después nuestro programa y dejarlo accesible desde fuera del emulador si tecleamos SAVE"nombre.bas",a (la opción A indica que se guarde en formato ASCII, en vez de compactado, y así lo podremos leer y modificar desde cualquier editor).

12. Borrar la pantalla

La orden de borrar la pantalla es sencilla: CLS, abreviatura de CLEAR SCREEN. En un equipo antiguo como los Amstrad CPC, el borrar la pantalla y redibujarla por completo en cada fotograma de un juego puede provocar parpadeos. Por eso, en el ejemplo anterior borrábamos la casilla que antes ocupaba nuestro personaje antes de redibujarlo. Eso no quita que deberíamos borrar al menos la pantalla una vez al principio del juego:
5 CLS

13. Uso de colores

La memoria de pantalla de un CPC es muy limitada (16 KB), así que si queremos tener muchos puntos en pantalla será a cambio de tener pocos colores, y si nos apetece usar muchos colores, la cantidad de puntos será menor y las imágenes serán menos nítidas.
Podemos escoger entre tres modos de pantalla:
  • Modo 0: 25 líneas de texto, con 20 caracteres cada una. En modo gráfico, esto supone poder usar 160x200 puntos, con 16 colores simultáneos, a elegir entre una paleta de 27 colores.
  • Modo 1: 25 líneas de 40 caracteres (320x200 puntos, con 4 colores, también a elegir entre 27).
  • Modo 2: 25 líneas de 80 caracteres (640x200 puntos, con 2 colores de 27).
Un CPC inicialmente arranca en "modo 1". Para cambiar de un modo a otro, se usa la orden MODE, seguida por el número de modo:
MODE 0
Si queremos que nuestro programa sea robusto, debería escoger un modo de pantalla nada más comenzar, para que no se comporte de forma incorrecta si el equipo estaba en un modo de pantalla distinto del que esperábamos, Cuando se cambia de modo, también se borrará la pantalla:
5 MODE 1
Tenemos una orden para cambiar el color de texto (PEN) y otra para el color de fondo (PAPER). A continuación de cualquiera de estas órdenes se indica el número de color que se quiere usar, de 0 a 15 (en modo 0; si estamos en un modo de mayor resolución, tendremos menos colores disponibles: 0 a 3 en modo 1, 0 a 1 en modo 2):
PAPER 1: PEN 3: PRINT "hola"
Los valores predefinidos para cada uno de los colores son:
Modo 2:
0: Azul (paleta 1)1: Amarillo intenso (paleta 24)
Modo 1:
0: Azul (paleta 1)1: Amarillo intenso (paleta 24)
2: Cyan claro (paleta 20)3: Rojo claro (paleta 6)
Modo 0:
0: Azul (paleta 1)1: Amarillo intenso (paleta 24)2: Cyan claro (paleta 20)3: Rojo claro (paleta 6)
4: Blanco (paleta 26)5: Negro (paleta 0)6: Azul claro (paleta 2)7: Magenta claro (paleta 8)
8: Cyan (paleta 10)9: Amarillo (paleta 12)10: Azul pálido (paleta 14)11: Rosa (paleta 16)
12: Verde claro (paleta 18)13: Verde pálido (paleta 22)14: Parpadeo Azul/Amarillo15: Parpadeo azul cielo/Rosa
Pero esos valores se pueden redefinir a partir de los 27 colores de la paleta. Para redefinir un color utilizaremos "INK pluma, color". Por ejemplo, podemos hacer que el color de fondo sea púrpura con:
INK 0,7 : PAPER 0
O establecer el segundo color de texto (si estamos en modo 1 o modo 0) a verde lima con
INK 2,21 : PEN 2
La lista completa de colores que forman la paleta es:
0 - Negro (5)1 - Azul (0,14)2 - Azul claro (6)3 - Rojo4 - Magenta5 - Violeta6 - Rojo claro (3)7 - Púrpura8 - Magenta claro (7)
9 - Verde10 - Cyan (8)11 - Azul cielo (15)12 - Amarillo (9)13 - Gris14 - Azul pálido (10)15 - Anaranjado16 - Rosa (11)17 - Magenta pálido
18 - Verde claro (12)19 - Verde mar20 - Cyan claro (2)21 - Verde lima22 - Verde pálido (13)23 - Cyan pálido24 - Amarillo claro (1)25 - Amarillo pálido26 - Blanco (4)
También podemos cambiar el color del borde de la pantalla:
BORDER 23

14. Repetir mientras se cumpla una condición: el "bucle de juego"

Un juego típicamente realiza una serie de tareas que se repiten en cada "fotograma": comprobar qué teclas pulsamos, mover los enemigos y demás elementos del fondo, comprobar colisiones entre los elementos (que nos pueden dar puntos o hacer perder una vida) y dibujar todo en pantalla. Esta estructura repetitiva es lo que se suele conocer como el "bucle de juego".
Iremos completando esos detalles poco a poco, pero vamos a crear ya la estructura básica para ese bloque repetitivo. El bloque comienza por la orden WHILE (mientras), y termina con la orden WEND. En la orden WHILE hay que indicar la condición que hace que se repita. Por ejemplo, podemos crear una variable "terminado", que empiece teniendo el valor 0 (para indicar que no ha terminado la partida) y que más adelante cambie de valor para indicar cuando termine la partida (por ejemplo, si chocamos con un enemigo).
10 terminado=0
20 WHILE terminado = 0
100 WEND
De modo que el programa completo por ahora sería algo como:
5 MODE 1: INK 0,0: INK 1,20
10 x=10: y=5: velocidad=1: terminado=0
20 WHILE terminado = 0
30 LOCATE x,y
40 PRINT " "
50 x = x+velocidad
60 LOCATE x,y
70 PRINT CHR$(248)
80 IF x=1 OR x=40 THEN velocidad = -velocidad
90 FOR pausa = 1 TO 200: NEXT pausa
100 WEND
Ahora el programa se repite sin fin, porque aún no cambiamos el valor de la variable "terminado", así que para terminar de probarlo deberemos pulsar dos veces la tecla ESC de nuestro CPC.

15. Comprobar las teclas

Podemos saber si se ha pulsado alguna tecla mirando el valor de INKEY$. Es un texto, de modo que la variable en la que guardemos su valor deberá tener un nombre terminado con el simbolo $, para indicar que no va a almacenar valores numéricos sino caracteres:
tecla$ = INKEY$
Ahora tecla$ podrá tener valores como "w", "a", "s", "d" o la tecla que se haya pulsado... o bien una cadena vacía ("") si no se ha pulsado ninguna tecla. de modo que podríamos hacer que nuestro personaje se moviera con esas teclas así:
5 MODE 1: INK 0,0: INK 1,20
10 x=10: y=5: terminado=0
20 WHILE terminado = 0
30 LOCATE x,y
40 PRINT " "
42 tecla$ = INKEY$
44 IF tecla$="a" THEN x=x-1
46 IF tecla$="d" THEN x=x+1
48 IF tecla$="w" THEN y=y-1
50 IF tecla$="s" THEN y=y+1
52 IF tecla$="x" THEN terminado=1
60 LOCATE x,y
70 PRINT CHR$(248)
90 FOR pausa = 1 TO 200: NEXT pausa
100 WEND
La orden INKEY$ es fácil de usar y existe en casi cualquier versión de BASIC, pero tiene limitaciones: no funcionará correctamente si está activado el bloqueo de mayúsculas (porque la tecla "A" no nos devolverá "a" sino "A") y además tiene un cierto retardo antes de empezar a repetirse. En los Amstrad CPC existe una alternativa: la orden INKEY(x), que devolverá -1 si la tecla con código "x" no está pulsada. Por ejemplo, si sabemos que la tecla "abajo" tiene el código 2, podríamos comprobar si está pulsada con:
IF INKEY(2) <> -1 THEN ...
El problema es conocer los códigos de las teclas, pero están recopilados en la siguiente imagen:

Así, una versión alternativa del programa sería:


5 MODE 1: INK 0,0: INK 1,20
10 x=10: y=5: terminado=0
15 arriba=0: abajo=2: derecha=1: izqda=8: salir=63
20 WHILE terminado = 0
30 LOCATE x,y
40 PRINT " "
42 IF INKEY(arriba) <> -1 THEN y=y-1
44 IF INKEY(abajo) <> -1 THEN y=y+1
46 IF INKEY(derecha) <> -1 THEN x=x+1
48 IF INKEY(izqda) <> -1 THEN x=x-1
50 IF INKEY(salir) <> -1 THEN terminado=1
60 LOCATE x,y
70 PRINT CHR$(248)
90 FOR pausa = 1 TO 200: NEXT pausa
100 WEND