Nuclear Invaders para Camputers Lynx

Foro dedicado a la programación en todo tipo de sistemas clásicos.
dancresp
Amiga 1200
Amiga 1200
Mensajes: 1393
Registrado: 23 Dic 2008, 17:53
Sistema Favorito: MSX
primer_sistema: ZX81
Primera consola: Atari 2600
Gracias dadas: 3 veces
Gracias recibidas: 20 veces

Nuclear Invaders para Camputers Lynx

Mensajepor dancresp » 12 Jun 2014, 10:47

NucInv_4.gif
NucInv_4.gif (6.38 KiB) Visto 2456 veces


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":
NuclearInvaders_Lynx.rar
(2.46 KiB) Descargado 273 veces


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.

camputers-lynx-large.jpg
camputers-lynx-large.jpg (31.92 KiB) Visto 2456 veces


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.

Pale.gif
Pale.gif (48.79 KiB) Visto 2456 veces


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.

Pale_editor.gif
Pale_editor.gif (4.88 KiB) Visto 2456 veces


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.

NucInv_1.gif
NucInv_1.gif (4.03 KiB) Visto 2456 veces

NucInv_2.gif
NucInv_2.gif (4.35 KiB) Visto 2456 veces

NucInv_3.gif
NucInv_3.gif (6.29 KiB) Visto 2456 veces

NucInv_4.gif
NucInv_4.gif (6.38 KiB) Visto 2456 veces
Buscando la IP de la W.O.P.R.

Volver a “Programación”

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 13 invitados