EL JUEGO
Vuelven los invasores del espacio!!!
En el año 1977 intentaron invadir las ciudades de la tierra, y fracasaron.
Ahora vuelven con un malvado plan: destruir las centrales nucleares para dejar el planeta inhabitable.
Con la ayuda de nuestro tanque debemos evitar que cumplan con su objetivo.
Cada nivel lo componen 30 invasores, y al superarlo aparecerá una central más grande y los invasores deberán recorrer menos distancia para llegar a ella.
Destruye el UFO que aparece por la parte superior para conseguir puntos extras.
Pulsa “RETURN” en la pantalla de presentación para empezar la partida.
Descargar "Nuclear Invaders" en formato "TAP":
BLOQUES
He dividido el listado en 13 bloques:
- Declaración de las matrices.
- Control de nuestro tanque.
- Control de nuestro disparo.
- Mover UFO.
- Mover invasor.
- Destruir enemigo ó UFO.
- Perder una vida.
- Pasar Nivel.
- Presentación.
- Mostrar pantalla de juego.
- Cargar gráficos e inicializar variables.
- Rutinas varias.
- Bloques de gráficos.
COMO FUNCIONA
Todo el programa ocupa 174 líneas.
A continuación indico el principio de las distintas partes del programa:
10 - Definimos las matrices del juego.
30 – Llamada a rutinas para leer gráficos (3000)
35 – Ir a la presentación (2000).
100 – Comprobamos si se ha de mover nuestro tanque, mostrándolo en la nueva posición.
130 – Si hay un disparo en pantalla lo movemos, sino miramos si se ha pulsado disparo (RETURN).
170 – Si hay un UFO en pantalla lo movemos, sino decrementamos el contador (W).
200 – Rutina de movimiento de invasores. Se mueve uno distinto en cada pasada. Primero miramos si todavía hay invasores en la posición correspondiente (3 por posición), sino hay, salimos. Si tiene alguna velocidad asignada lo movemos, y sino mediante un número aleatorio decidimos si se ha de empezar a mover. Durante el movimiento cambiamos su animación y miramos si ha llegado a la central nuclear.
250 – Contador del próximo invasor a mover (M).
260 – Si no se han destruido todos los invasores (T) volvemos al REPEAT en 100, y si no quedan seguimos hasta 300.
300 - Código de pasar nivel. Se ejecuta cuando destruimos los 30 invasores. Se incrementa el control de dificultad (C) que indicará la anchura de la central nuclear.
400 – Esta rutina se ejecuta cuando el disparo llega a la altura de los invasores o del UFO. Aquí se calcula si se ha tocado un invasor o el UFO y actúa en consecuencia. En 410 se destruye un invasor y en 450 se destruye el UFO.
500 – Rutina que se ejecuta cuando un invasor llega a la central nuclear. Se borra una vida. Si quedan vidas volvemos a empezar el nivel y sino vamos a la pantalla de presentación después de una pausa.
2000 – Pantalla de presentación del juego.
2100 – Borrado de la pantalla de presentación. Mensaje al jugador uno para que esté listo y se dibuja la central nuclear.
2800 – Posiciona y muestra a los invasores y nuestro tanque en pantalla. Reinicia el valor de ciertas variables.
3000 – Cargamos los gráficos desde las líneas DATA.
5000 – Rutina para imprimir un número en un marcador. Pasar el valor en (I) y la posición en (N).
5200 – Rutina de borrado de parte de la pantalla, respetando los marcadores superiores y inferiores.
9000 – Datos de los gráficos UDG del juego.
EL LISTADO
Código: Seleccionar todo
10 DIM X(10),Y(10),Q(10),S(10),G(10),I$(66),E$(4)
30 GOSUB 3000
35 GOTO 2000
*** Mover tanque
100 REPEAT
110 IF INP(&0280)<>247 THEN GOTO 120
112 IF H>12 THEN LET H=H-3
114 ELSE GOTO 130
116 PRINT @ H,220;"mno ";
120 IF INP(&0180)<>247 THEN GOTO 130
122 IF H>102 THEN GOTO 130
124 PRINT @ H,220;" mno";
126 LET H=H+3
*** Control disparo
130 IF D THEN GOTO 150
140 IF INP(&0980)<>247 THEN GOTO 170
142 IF H+6>J AND H<O-3 THEN GOTO 170
145 LET D=210,G=H+3
148 GOTO 166
150 PRINT @ G,D," ";
155 IF D<>30 THEN GOTO 165
160 LET D=0
162 GOTO 170
165 LET D=D-20
166 IF D<170 THEN GOTO 400
168 PRINT @ G,D;"s";
*** Control UFO
170 IF U THEN GOTO 185
175 LET W=W-1
180 IF W THEN GOTO 200
185 IF U>105 THEN GOTO 195
186 LET U=U+2
188 PRINT @ U,30;" pqr";
190 GOTO 200
195 PRINT @ U,30;" ";
196 LET U=0,W=200
*** Control Invasores
200 IF Q(M)=0 THEN GOTO 250
210 IF S(M) THEN GOTO 240
215 IF RND<0.7 THEN GOTO 250
220 LET S(M)=INT(RND*3)+1
225 IF M>5 THEN LET S(M)=-S(M)
240 LET F=X(M),X(M)=F+S(M)
245 PRINT @ F,Y(M);MID$(I$,M*6+A*3,3);
248 IF ABS(60-F)<E THEN GOTO 500
250 IF M=10 THEN LET M=1,A=NOT(A)
255 ELSE LET M=M+1
260 UNTIL T=0
*** Pasar nivel
300 PAUSE 30000
305 LET N=22
310 GOSUB 5200
315 IF C<6 THEN LET C=C+1
320 GOTO 2500
*** ¿Que toca el disparo? (410=Invasor / 450=UFO)
400 IF D=30 AND G>U+2 AND G<U+12 THEN GOTO 450
402 LET F=(D-50)/20
404 IF F<1 THEN GOTO 168
406 IF G<50 THEN LET I=3,N=114
408 ELSE LET I=0,F=F+5,N=114
410 IF G<X(F)+I-1 OR G>X(F)+I+6 THEN GOTO 168
420 PRINT @ X(F),Y(F);MID$(E$,1+(I<>3),3);
422 PAUSE 1000
424 PRINT @ X(F)+I,Y(F);" ";
430 LET S(F)=0,Q(F)=Q(F)-1,P=P+G(F),T=T-1,X(F)=N
445 GOTO 470
450 PRINT @ U,30;E$;
455 PAUSE 1000
460 LET I=U,U=0,W=200,F=INT(RND*3+1)*50,P=P+F
465 PRINT @ I+3,30;F;" ";
466 PAUSE 5000
468 PRINT @I,30;" ";
470 LET D=0,N=15,I=P
475 GOSUB 5000
480 GOTO 170
*** Perder vida / Fin partida
500 PAUSE 10000
510 IF L=1 THEN GOTO 540
520 LET L=L-1,A$=STR$(L)+" "
522 IF L=1 THEN GOTO 530
524 FOR F=2 TO L
526 LET A$=A$+"mno"
528 NEXT F
530 PRINT @ 9,240;A$+" ";
532 LET N=22
534 GOSUB 5200
536 GOTO 2500
540 PRINT @ 48,190;"GAME OVER";
545 PAUSE 90000
550 IF R<P THEN LET R=P
*** Pantalla presentación
2000 CLS
2005 PRINT @ 9,0,"SCORE<1> HI-SCORE SCORE<2>";
2010 LET N=15,I=P
2015 GOSUB 5000
2020 LET N=57,I=R
2025 GOSUB 5000
2030 PRINT @ 9,240;" mnomno"
2035 PRINT @ 90,240;"CREDIT 00";
2040 PRINT @ 57,50;"PLAY";
2045 PRINT @ 39,70;"NUCLEAR INVADERS";
2050 PRINT @ 30,110;"*SCORE ADVANCE TABLE*";
2055 PRINT @ 39,130;"pqr =? MYSTERY";
2060 PRINT @ 42,150;"cd =30 POINTS";
2065 PRINT @ 42,170;"gh =20 POINTS";
2070 PRINT @ 42,190;"kl =10 POINTS";
2090 LET K=GETN
*** Inicio partida: Escenario
2100 LET N=23,P=0,L=3,C=3
2105 GOSUB 5200
2110 PRINT @ 42,120;"PLAY PLAYER<1>"; <================================
2115 FOR F=1 TO 10
2120 PRINT @ 15,10;" ";
2125 PAUSE 1000
2130 PRINT @ 15,10;"0000";
2135 PAUSE 1000
2140 NEXT F
2145 LET N=23
2150 GOSUB 5200
2155 PRINT @ 9,240;"3";
2160 PRINT @ 6,230;"uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu";
2500 LET F=(C+1)*2+2,A$="",B$="",E=(C*6+12)/2,J=(19-C)*3,O=J+(F*3)
2510 PRINT @ J,60;LEFT$(D$,F);
2515 PRINT @ J,170;LEFT$(D$,F);
2520 FOR F=1 TO C+1
2525 LET A$=A$+"vw",B$=B$+"xy"
2530 NEXT F
2535 LET A$="t"+A$+"t",B$="t"+B$+"t"
2540 FOR F=70 TO 150 STEP 20
2545 PRINT @ J,F,A$;
2550 PRINT @ J,F+10,B$;
2560 NEXT F
*** Inicio partida: Mostrar invasores y tanque
2800 FOR F=1 TO 5
2805 LET Y(F)=F*20+50,Y(F+5)=Y(F),X(F)=3,X(F+5)=114
2810 NEXT F
2815 FOR F=1 TO 10
2820 PRINT @ X(F),Y(F)MID$(I$,F*6,3);
2825 LET Q(F)=3,S(F)=0
2830 NEXT F
2835 PRINT @ 12,220,"mno";
2840 LET H=12,M=1,D=0,U=0,W=200,T=30,A=0
2845 GOTO 100
*** Pantalla Instrucciones, lectura gráficos e inicializar variables
3000 CLS
3005 PRINT @ 39,0;"NUCLEAR INVADERS";
3010 PRINT @ 27,70;"CONTROLS: LEFT = Z";
3015 PRINT @ 57,80;"RIGHT = X";
3020 PRINT @ 57,90;"FIRE = RETURN";
3030 PRINT @ 15,210;"PROGRAM DEDICATED TO RON & PETE";
3035 PRINT @ 33,240;"(C)SCAINET SOFT, 2014";
3040 LET D$="tttttttttttttttt",R=0,P=0,E$=" "+CHR$(250)+CHR$(251)+" "
3045 RESERVE HIMEM-270
3048 DPOKE GRAPHIC,HIMEM
3050 FOR F=0 TO 269
3055 READ A
3060 POKE LETTER(225)+F,A
3065 NEXT F
3070 PRINT @ 33,160;"*PRESS KEY TO START*";
3075 FOR F=1 TO 10
3076 READ G(F)
3080 NEXT F
3085 LET I$=" cd ab gh ef gh ef ij kl ij klcd ab gh ef gh ef ij kl ij kl ",Z$="000"
3090 LET K=GETN
3095 RETURN
*** Rutinas varias (5000=Marcador / 5200=CLS)
5000 LET A$=Z$+STR$(I)
5005 PRINT @ N,10,RIGHT$(A$,4);
5010 RETURN
5200 FOR F=30 TO N*10 STEP 10
5205 PRINT @ 6,F," ";
5210 NEXT F
5215 RETURN
*** Gráficos del juego y puntos según invasor
9000 DATA 1,3,7,13,15,5,8,4,0,0,32,48,56,44,60,40,4,8,0,0
9005 DATA 1,3,7,13,15,2,5,10,0,0,32,48,56,44,60,16,40,20,0,0
9010 DATA 8,36,47,59,63,31,8,16,0,0,4,9,61,55,63,62,4,2,0,0
9015 DATA 8,4,15,27,63,63,40,6,0,0,4,8,60,54,63,63,5,24,0,0
9020 DATA 3,31,63,57,63,14,25,12,0,0,48,62,63,39,63,28,38,12,0,0
9025 DATA 3,31,63,57,63,6,13,48,48,62,63,39,63,24,44,3,0,0
9030 DATA 0,0,0,15,31,31,31,31,0,0,8,28,28,63,63,63,63,63,0,0,0,0,0,56,60,60,60,60,0,0
9035 DATA 0,0,3,7,13,31,7,2,0,0,0,63,63,63,45,63,12,0,0,0,0,0,48,56,44,62,56,16,0,0
9040 DATA 0,8,8,8,8,8,0,0,0,0,47,47,47,0,61,61,61,0,0,0,0,0,0,0,0,0,63,0,0,0
9045 DATA 3,12,19,16,17,19,17,21,0,0,48,12,50,2,34,50,34,42,0,0
9050 DATA 22,23,22,18,16,12,3,0,0,0,26,58,26,18,2,12,48,0,0,0
9055 DATA 2,17,8,4,48,2,9,18,0,0,16,34,4,8,3,16,36,18,0,0
9500 DATA 10,20,20,30,30,10,20,20,30,30
APUNTES FINALES
La invasión continúa con la octava versión del juego, que sigue a las de DRAGON, MSX, ORIC, Jupiter ACE, Spectrum, Amstrad CPC y CP/M-86.
Esta versión se ha programado a partir de la del ORIC ya que los gráficos también son de 6 pixels de ancho, aunque en este caso tienen una altura de 10 pixels en lugar de los 8 del ORIC. Por eso al final del cada gráfico he añadido dos 0. Como ningún invasor ocupa más de 12 pixels de ancho, han entrado perfectamente en dos caracteres. Para el tanque y el UFO he tenido que usar 3 caracteres. He redefinido los caracteres comprendidos entre el CHAR 225 y el 251, que por defecto contienen los gráficos que aparecen cuando arranca el sistema.
En esta versión también muestro una pantalla previa de instrucciones, con dedicatoria incorporada, donde indico las teclas de control. Mientras, se van redefiniendo los gráficos e inicializando algunas matrices y variables.
He de dejar claro que a falta del equipo real todo el desarrollo se ha realizado con el emulador PALE.
Esto no ha impedido que haya aprendido muchas cosas sobre este equipo, y la verdad es que me ha sorprendido muy gratamente en algunos aspectos y me ha decepcionado en otros…
Sistema Camputers Lynx
Para esta ocasión el equipo elegido ha sido el Camputers Lynx. Un ordenador del año 1983 equipado con un Z80 a 4MHz, 16 KB de ROM y 48 KB de RAM.
Dispone de un chip de video 6845 de Motorola que proporciona una resolución de 256x248 pixels y 8 colores, con una matriz de caracteres de 6x10 y un modo de texto de 40x24 caracteres, que realmente es un modo gráfico.
Cada punto de la pantalla puede tener un color distinto, cosa que lo hace muy potente para época, pero que por motivos de diseño lo limita en temas tan básicos como en poder hacer un SCROLL o saber que hay en una posición de la pantalla si no es mediante rutinas en ensamblador.
Como sistema operativo tiene un BASIC bastante compatible con el de Microsoft, aunque limitado en algunos aspectos.
Usando el emulador PALE
Lo primero que llama la atención de este emulador es que se abre en dos partes. Por un lado hay la pantalla en una ventana y por el otro lado está el panel de control en otra ventana. Es posiblemente el panel de control más feo y liado que puedes encontrar en un emulador. Da la sensación de que se hizo provisionalmente, y así se ha quedado. Pero bueno, la verdad es que funciona bien, aunque tengo serias dudas de que la velocidad la emula al 100%.
Para el desarrollo me he limitado a usar el botón “Load TAP” para cargar el programa que previamente he grabado desde la pantalla principal con “SAVE nombre”, ya que el botón “Save to TAP” lo grababa con un nombre raro.
Por otro lado seleccionas el tamaño de la ventana con la lista desplegable “Display” a “2x” en mi caso, y la velocidad la he dejado al “100%” aunque en equipos más rápidos lo he tenido que reducir al “50%”.
El botón “Printer” abre una ventana pero he sido incapaz de sacar un listado del programa.
Me he quedado con las ganas de experimentar con el sonido porque por lo visto no está emulado.
Por el resto, la mayoría de botones son prescindibles e incluso en muchos casos no se sabe bien bien que hacen.
El editor del Camputers Lynx
Mi primera sorpresa ha sido descubrir que no se pueden poner varias instrucciones en una misma línea separadas con los dos puntos. Ahora mismo no recuerdo ningún otro equipo que tenga esta limitación, excepto el ZX-81.
Al arrancar el equipo entras en un modo prompt similar al del BBC Micro. Si pones una expresión matemática actúa como una calculadora sin necesidad de poner el PRINT delante. Si empieza con un número y hay una instrucción BASIC la guarda en el programa, y si la instrucción no comienza con un número la ejecuta. Así de simple, pero esto obliga a que para borrar una línea del programa BASIC lo tengas que hacer con “DEL número_línea[,hasta_línea]”.
Otra cosa muy original es que los números de línea pueden contener decimales. Así puede haber una línea 10, otra 10.5 y la 11, por ejemplo. Es la primera vez que lo veo en mi vida.
La edición de las líneas BASIC ya introducidas es muy sencilla. Con “Control+E” entras en el modo edición en el que te pregunta la línea a editar. Al indicarla se entra en un modo edición igual al del Amstrad CPC o Spectrum en el que te solo te puedes mover a lo largo de la línea seleccionada.
Una particularidad de su editor es que al hacer un LIST muestra el listado por pantalla pero sin hacer un Scroll al llegar a la última fila. Así, continúa el listado en la primera línea, dando una sensación un tanto “extraña”. Pero bueno, listar lista.
La separación de valores en los LIST o DEL, entre otros, se hace mediante una coma y no con un guión como en otros BASIC.
Durante el listado del programa se encarga de tabular las líneas que están dentro de bucles. Esto facilita su lectura.
Al introducir una línea y pulsar “RETURN” se revisa su sintaxis. Si se encuentra un error avisa, no se introduce en el programa y se vuelve al prompt. Se debe pulsar “Ctrl+Q” para recuperarla y realizar las correcciones necesarias.
Para introducir los caracteres especiales, que he usado para redefinir con los gráficos del juego, se debe pulsar “Ctrl+1” y manteniendo pulsada la tecla “Shift” se pulsa la tecla correspondiente. Pulsar “Ctrl+1” de nuevo para desactivar.
Las líneas en BASIC pueden tener un tamaño máximo de 240 caracteres.
El BASIC del Camputer Lynx
Su BASIC es bastante más potente en algunos aspectos pero bastante deficiente en otros. Así, permite el uso de bucles WHILE/WEND, REPEAT/UNTIL y admite el uso de PROCEDURES.
Los nombres de las variables solo pueden tener una letra y distingue entre mayúsculas y minúsculas, limitándolo a 52 variables numéricas, pero solo 26 alfanuméricas. Si se quieren más hay que usar matrices, que también están limitadas.
Las matricen numéricas solo admiten una dimensión, pero no permite hacer matrices con cadenas. Cuando el DIM hace referencia a una variable alfanumérica simplemente indica el tamaño de esa cadena, no sus dimensiones. Por defecto una cadena no puede tener más de 16 caracteres.
Con “PRINT @ x,y” puedes poner un carácter en cualquier parte de la pantalla. Verticalmente se puede poner en un pixel cualquiera, y horizontalmente se puede poner en posiciones que el sistema multiplica por 2. Así, un carácter tiene 6 pixels de ancho pero solo se puede poner en tres posiciones. Sea como sea, esto me ha permitido hacer que los invasores puedan tener hasta tres velocidades distintas y que el movimiento sea más suave que en los otros sistemas, excepto el MSX.
Es conveniente acabar los PRINT con un punto y coma ya que hace un efecto extraño borrando parte de la línea siguiente, y teniendo en cuenta que no es muy rápido imprimiendo en pantalla, es mejor evitarlo. Ignoro el motivo pero de esa forma lo hace bien y mucho más rápido.
Al igual que el SPECTRUM, para asignar un valor a una variable se puede usar la instrucción LET, que permite asignar varios valores en una misma línea separando las asignaciones con una coma. Si se omite LET el intérprete lo introduce automáticamente al guardar la línea.
El acceso al teclado es limitado ya que GET$ y GETN quedan a la espera de que pulses una tecla, y KEY$ y KEYN no tienen auto repetición. Para evitar esto he accedido a leer el puerto del teclado con INP(puerto), y a base de probar he encontrado los necesarios.
También es la primera vez que veo una condición IF/THEN/ELSE en que el ELSE se debe introducir en la siguiente línea ya que si lo pones en la misma da un error de sintaxis. Esto hace que los programas sean más largos que en otras versiones.
Y ya acabo...
Una sistema muy peculiar, con aspectos muy interesantes y potentes, pero con algunas limitaciones incomprensibles.
Es como un pupurri de otros sistemas y a medida que lo usaba iba pensando, “mira como el tal equipo”... Tema de matrices como el ATARI XL/XE, las variables como una CASIO PB, el editor como el AMSTRAD/SPECTRUM, los bucles como el BBC/AMSTRAD/ORIC, etc...
Con todo, la verdad es que he disfrutado mucho descubriendo sus características. Vale la pena probarlo.
Ahora solo me queda verlo funcionar en un LYNX real para comprobar su rendimiento.
Y como siempre…
Os invito a probarlo.