Space Invasion para ATARI XE/XL

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

Space Invasion para ATARI XE/XL

Mensajepor dancresp » 19 Mar 2013, 20:15

Atari_1.jpg
Atari_1.jpg (59.98 KiB) Visto 5116 veces


EL JUEGO
Nuevo intento de los Space Invaders para hacerse con el control de nuestro planeta !!!

¿Para que ir dando tumbos cuando puedes ir directo a tu objetivo?

Los invasores van bajando en columnas y con la ayuda de nuestro tanque debemos seleccionar el tipo de invasor y disparar.
Si el invasor está en esa columna será destruido y el resto retrocederán una posición.
Hay que evitar que lleguen a la zona de búnkeres o la victoria será suya.

Cada nivel lo componen 35 invasores y disponemos de 50 disparos para acabar con ellos.
Al superar un nivel llegamos a otro en el que los invasores avanzar más rápidamente.

El juego guarda la máxima puntuación alcanzada en una partida.


BLOQUES
He dividido el listado en 12 bloques:

- Declaración de las matrices.
- Control de nuestro tanque.
- Control de nuestro objetivo.
- Control de nuestro disparo.
- Mover invasor.
- Perder una vida.
- Pasar Nivel.
- Presentación.
- Mostrar pantalla de juego.
- Cargar UDG.
- Rutinas varias.
- Bloques de gráficos.


COMO FUNCIONA
Todo el programa ocupa 77 líneas.

A continuación indico el principio de las distintas partes del programa:

10 - Definimos las matrices del juego.
20 - Llamada a rutina para leer gráficos
50 - Mostrar la pantalla de presentación del juego.
100 – Comprobamos si se ha de mover horizontalmente nuestro tanque.
120 – Comprobamos si hemos de cambiar el invasor “objetivo” de la columna activa.
150 – Comprobamos si se ha de disparar. Se revisa si el invasor “objetivo” está en la columna, actuando en consecuencia.
160 – En caso de disparo revisamos si el invasor seleccionado está en la columna que apuntamos.
170 – En función del invasor asignamos la puntuación (F). Si es 9, es el UFO y cambiamos los puntos a 25.
175 – Reproducimos un sonido y actualizamos el marcador.
180 – Este bucle elimina el invasor de la columna.
200 – Si el contador de velocidad (W) no llega al valor deseado se incrementa en uno y se salta a la línea 290.
210 – Se selecciona una columna aleatoriamente y si quedan invasores por salir, salen, y si no se añade un espacio en la columna.
220 – Se comprueba si la columna ha llegado al búnker. En caso afirmativo se salta a la línea de perder vida (500).
250 – Incorpora el invasor en la matriz, desplazando el resto una posición.
260 – Refresca la columna de invasores seleccionada.
290 – Bucle que utiliza la variable de sistema “TIME” para que el juego tenga una velocidad constante.
300 – Si la variable de estado (E) se mantiene a 0 se vuelva a la línea 100.
400 – Rutina que se ejecuta cuando un invasor llega al búnker. Si nos queda alguna vida se actualizan los marcadores, sino muestra el mensaje de “GAME OVER” y después de una pausa volvemos a la pantalla de presentación.
500 – Rutina de nivel superado. Se incrementa en 1, pero si estamos en el 6 volvemos al 4.
2000 – Pantalla de presentación del juego.
2090 – Llamada a la rutina que vacía el buffer del teclado y espera que pulsemos una tecla para empezar el juego.
2100 – Muestra la parte de la derecha de la zona de juego.
2300 – Inicializamos las variables de Nivel (L), Vidas (V) y Puntuación (S).
2500 – Se actualiza el estado de las cinco columnas de invasores y del invasor “objetivo”.
2510 – Muestra la parte izquierda de la zona de juego, donde realmente se desarrolla la acción.
2550 – Se reinicializan ciertas variables del juego. Posición Tanque (P), Invasores pendientes (O), Munición (B), Estado (E).
3000 – Inicio de la rutina que redefine los caracteres. Reducimos el RAMTOP en 1KB y ponemos un mensaje de copyright.
3005 – Ocultamos el cursor y cambiamos los colores de letra, fondo y borde.
3010 – Copiamos parte de los caracteres desde la ROM a la RAM, y modificamos la dirección que indica donde están.
3015 – Completamos la redefinición leyendo los datos desde nuestras DATA. Redefinimos las minúsculas.
3020 – Asignamos los gráficos de los distintos elementos a variables.
4000 – Rutina de Pausa, pasando en valor en (I).
4100 – Rutina para imprimir los valores de “REST” y Munición “AMMO”. Posición vertical en (Y) y valor en (N).
4200 – Rutina para imprimir la puntuación y el récord en formato de 4 cifras. Posición horizontal en (Y) y valor en (N).
4300 – Rutina que espera la pulsación de una tecla, y la guarda en (K). A continuación borra el valor del buffer de teclado.
4400 – Rutina que reproduce un sonido de una frecuencia (N) durante un breve periodo de tiempo.
4500 – Rutina para hacer un borrado parcial de la pantalla.
9000 – DATA con los distintos gráficos del juego.


EL LISTADO

Código: Seleccionar todo

10 DIM T$(2),G$(20),C$(3),I$(40),T(5),A$(1),S$(4),X$(4)
20 GOSUB 3000
50 GOSUB 2000

    ' Controlar nuestro tanque
100 K=PEEK(764):IF K=255 THEN 200
105 POKE 764,255:IF K=28 THEN GRAPHICS 1:GRAPHICS 0:POKE 752,0:END
110 IF K=23 THEN IF P>1 THEN P=P-1:POSITION P*3+2,21:PRINT T$;"   "
115 IF K=22 THEN IF P<5 THEN P=P-+:POSITION P*3-1,21:PRINT "   ";T$
120 IF K<>7 THEN 150
130 T(P)=T(P)+1:IF T(P)>9 THEN T(P)=1
140 POSITION P*3+2,19:F=T(P)*2+1:PRINT G$(F,F+1)

    ' Disparo contra un invasor
150 IF K<>12 OR B=0 THEN 200
155 N=121:GOSUB 4400:B=B-1:Y=3:N=B:GOSUB 4100:A$=STR$(T(P)):I=0:Z=(P-1)*8
160 FOR F=8 TO 1 STEP -1:IF A$=I$(Z+F,Z+F) THEN I=F:F=0
165 NEXT F:IF I=0 THEN 200
170 F=T(P):IF F=9 THEN F=25
175 S=S+F:Y=5:N=S:GOSUB 4200:M=M+1:IF M=35 THEN 500
180 FOR F=I TO 7:I$(Z+F,Z+F)=I$(Z+F+1,Z+F+1):NEXT F
190 F=P:GOTO 260

    ' Movimiento de los invasores
200 W=W+1:IF W<40-L*5 THEN 300
210 N=81:GOSUB 4400:W=0:F=INT(RND(0)*5)+1:I=0:IF O>0 THEN I=INT(RND(0)*9)+1:O=O-1:Y=5:N=O:GOSUB 4100
220 E=0:Z=F*8-1:IF I$(F,F)<>"0" THEN E=1
250 Z=(F-1)*8+8:FOR J=8 TO 2 STEP -1:I$(Z,Z)=I$(Z-1,Z-1):Z=Z-1:NEXT J:I$(Z,Z)=STR$(I)
260 Z=F*3+2:I=(F-1)*8:N=3:FOR J=1 TO 7+E:POSITION Z,N:F=VAL(I$(I+J,I+J))*2+1:PRINT G$(F,F+1):N=N+2:NEXT J
300 IF E=0 THEN 100

    ' El invasor llega al bunker. Perdemos vida.
400 FOR Z=81 TO 121 STEP 5:N=Z:GOSUB 4400:NEXT Z:I=750:GOSUB 4000:GOSUB 4310:IF V=1 THEN 450
410 V=V-1:POSITION 3,23:PRINT STR$(V);" ";
420 IF V>1 THEN FOR F=2 TO V:PRINT T$;:NEXT F
430 PRINT "  ";:GOSUB 2500:GOTO 100
450 POSITION 11,23:PRINT "<GAME OVER>";:I=1500:GOSUB 4000:IF S>R THEN R=S
460 GOSUB 4500:GOTO 50

    ' Pasamos nivel
500 FOR Z=1 TO 3:N=81:GOSUB 4400:N=91:GOSUB 4400:NEXT Z:I=750:GOSUB 4000:L=L+1:IF L=6 THEN L=4
510 POSITION 33,9:PRINT L:GOSUB 2500:GOSUB 4310:GOTO 100

     ' Pantalla de presentación
2000 POSITION 2,0:PRINT " SCORE<1>     HI-SCORE     SCORE<2>"
2020 Y=5:N=S:GOSUB 4200:Y=18:N=R:GOSUB 4200
2030 POSITION 18,4:PRINT "PLAY":POSITION 13,6:PRINT "SPACE INVASION"
2040 POSITION 9,9:PRINT "*SCORE ADVANCE TABLE*":PRINT
2050 FOR F=1 TO 4:Z=F*2:PRINT "     ";G$(Z+1,Z+2);"=";STR$(F);" POINTS * ";
2060 PRINT G$(Z+9,Z+10);"=";STR$(F+4);" POINTS":PRINT:NEXT F
2070 PRINT "            ";G$(19,20);"=25 POINTS"
2075 PRINT:PRINT:PRINT " __________________________________"
2080 POSITION 3,23:PRINT "3 ";T$;T$;"             ";:POSITION 29,23:PRINT "CREDIT 00";
2085 GOSUB 4310:GOSUB 4300:GOSUB 4500
2100 POSITION 24,3:PRINT "* AMMO : 50":POSITION 24,5:PRINT "* REST : 35":POSITION 24,9: PRINT "* LEVEL: 1"
2110 POSITION 24,14:PRINT "* KEYS:":POSITION 26,16:PRINT " Z : LEFT":POSITION 26,17:PRINT " X : RIGHT"
2120 POSITION 26,18:PRINT "RTN : FIRE":POSITION 26,19:PRINT " *  : CHANGE"
2300 L=1:V=3:S=0:Y=5:N=S:GOSUB 4200
2500 FOR F=1 TO 5:T(F)=1:NEXT F:I$="0000000000000000000000000000000000000000"
2510 FOR F=3 TO 16:POSITION 3,F:PRINT "w                w":NEXT F
2520 PRINT "   "+C$+C$+C$+C$+C$:POSITION 5,21:PRINT "      ";T$;"      "
2540 POSITION 3,19:PRINT "> ab ab ab ab ab <"
2550 P=3:W=0:E=0:O=35:M=0:B=50:Y=3:N=B:GOSUB 4100:Y=5:N=O:GOSUB 4100
2560 RETURN

     ' Rutina definir UDG (gráficos de usuario)
3000 POKE 106,PEEK(106)-5:GRAPHICS 0:POSITION 9,11:PRINT "(C) SCAINET SOFT, 2013 ";
3005 POKE 710,0:POKE 709,14:POKE 712,1:POKE 752,1
3010 UDG=(PEEK(106)+1)*256:FOR I=0 TO 775:POKE UDG+I,PEEK(57344+I):NEXT I:POKE 756,UDG/256
3015 FOR F=UDG+776 TO UDG+959:READ I:POKE F,I:NEXT F
3020 T$="st":G$="  abcdefghijklmnopqr":C$="uv ":R=0
3030 RETURN

     ' Rutinas varias (4000-Pausa, 4100-Valores, 4200-Marcadores, 4300-PressKey, 4400-Sound, 4500-Cls)
4000 FOR F=1 TO I:NEXT F:RETURN
4100 POSITION 33,Y:PRINT STR$(N);" ";:RETURN
4200 X$=STR$(N):S$="0000":N=LEN(X$):S$(5-N,4)=X$:POSITION Y,1:PRINT S$:RETURN
4300 K=PEEK(764):IF K=255 THEN 4300
4310 POKE 764,255:RETURN
4400 SOUND 0,N,10,15:I=10:GOSUB 4000:SOUND 0,0,0,0:RETURN
4500 FOR F=3 TO 21:POSITION 2,F:PRINT "                                   ":NEXT F

     ' Datos de los UDG
9000 DATA 1,3,7,16,15,5,8,4,128,192,224,176,240,160,16,32
9010 DATA 8,4,15,27,63,63,40,6,32,64,224,176,248,248,40,192
9020 DATA 3,31,63,57,63,14,25,12,192,248,252,156,252,112,152,48
9030 DATA 3,7,13,15,6,3,4,2,192,224,176,240,96,192,32,64
9040 DATA 1,3,7,13,15,2,5,10,128,192,224,176,240,64,160,80
9050 DATA 8,36,47,59,63,31,8,16,32,72,232,184,248,240,32,16
9060 DATA 3,31,63,57,63,6,13,48,192,248,252,156,252,96,176,12
9070 DATA 3,7,13,15,6,3,2,4,192,224,176,240,96,192,64,32
9080 DATA 0,7,31,63,109,255,57,16,0,224,248,252,182,255,156,8
9090 DATA 1,3,3,127,255,255,255,255,0,128,128,252,254,254,254,254
9100 DATA 31,63,127,255,255,252,248,248,248,252,254,255,255,63,31,31
9110 DATA 60,36,60,24,24,60,36,60


APUNTES FINALES
Este es el primer juego que hago para el sistema ATARI de 8 bits, y me ha servido para comprobar las limitaciones de su BASIC, bastante estándar pero con importantes limitaciones y engorros.A diferencia de las versiones ELECTRON y MSX, este sistema no tiene búfer de teclado. Bueno, ni siquiera tiene instrucciones para leerlo y se ha de hacer con un PEEK(764). Esto hace que la pulsación de las teclas no sea muy fiable a la hora de cambiar el invasor objetivo. Una vez leído el teclado hay que hacer “POKE 764,255” para borrar la tecla pulsada.Los gráficos del juegos son de 16x8, pero se han conseguido redefiniendo los caracteres de 8x8, y que no usan el estándar ASCII. Este BASIC no tiene comandos para redefinir caracteres y se ha de hacer mediante un proceso un tanto especial. El proceso consiste en rebajar el RAMTOP en 1KB para guardar nuestro propio juego, copiar mediante un bucle los datos desde la ROM a la RAM que hemos reservado, poner nuestros propios caracteres mediante un READ y un POKE en las posiciones
correspondientes y indicarle al sistema la nueva dirección del juego de caracteres.

Una vez se conoce el método no es complicado hacerlo, pero la ejecución lleva un tiempo porque este sistema no es especialmente rápido con los bucles.
Por otro lado, si ejecutamos la rutina dos veces funciona mal, con lo que antes de volver a ejecutar es necesario pulsar el botón “RESET”, que no borra el programa pero cambia ciertas variables del sistema.
Respecto a las variables, este sistema solo dispone de un único sistema de variables numéricas. En otros sistemas, el uso de variables enteras acelera los cálculos.
Me ha sorprendido la inexistencia de matrices alfanuméricas, pero si numéricas. Con el comando DIM indicas el tamaño total de una variable alfanumérica, pero usando el índice solo accedes a una posición concreta. Para usarlo como matrices te tienes que montar tú mismo todo el sistema de organización, haciendo, por ejemplo, que todos los valores tengan el mismo tamaño. Las matrices numéricas, de una única dimensión, funcionan sin problemas.

Tampoco dispone de instrucciones tipo LEFT, RIGHT, MID, TRIM o USING. Así, al adaptar el juego he tenido que solucionarlo de otras formas. Pero como se ve, se ha podido hacer.

El bucle principal de desarrollo va de la línea 100 hasta la 300, 21 líneas en total. Aquí se controla el tanque, el disparo y el movimiento de los invasores.

He eliminado todos los cálculos posibles y todos los AND/OR posibles. Uso un IF y si no se cumple ya no tengo que comprobar más valores.

El rendimiento del juego es bastante estable excepto cuando se redibujar una columna de invasores. No he podido usar la variable de sistema TIME, que se incrementa en 1 varias veces por segundo y es útil para fijar la velocidad de un juego.

Si no fuera por el tema del teclado, el juego sería casi idéntico a la versión del ELECTRON ya que los dos funcionan a 40 columnas. Por ello y el TIME, ésta es la versión más floja de las tres que he realizado.

Para el tema de sonido, en el que sigo siendo un perfecto inútil, he usado el comando SOUND mediante la rutina de la línea 4500. Simplemente paso un valor como parámetro y se reproduce un sonido. El sistema es bastante más potente del uso que le he dado yo.

Respecto a la grabación del programa, se hace con un simple CSAVE, sin indicar nombre. Mientras graba o carga va sonando por el altavoz, y según he comprobado va grabando o leyendo bloques de 128 bytes. Es lento pero aparentemente seguro.

Como apunte final, me ha gustado programar este juego en el ATARI 800XL. Su teclado es fiable y muy retro. Hacía tiempo que deseaba hacer algo con él, y creo que este juego es perfecto para un primer contacto. Para el próximo proyecto haré uso de SPRITES.

Para terminar, todo este desarrollo se ha programado en un ATARI 800XL auténtico.

Os invito a probarlo

atari2.jpg
atari2.jpg (51.79 KiB) Visto 5116 veces


atari3.jpg
atari3.jpg (59.08 KiB) Visto 5116 veces

atari4.jpg
atari4.jpg (51.87 KiB) Visto 5116 veces

atari5.jpg
atari5.jpg (64.53 KiB) Visto 5116 veces

atari6.jpg
atari6.jpg (85.37 KiB) Visto 5116 veces
Buscando la IP de la W.O.P.R.

Avatar de Usuario
zitror
Amiga 2500
Amiga 2500
Mensajes: 5349
Registrado: 02 Jul 2006, 00:16
Sistema Favorito: Spectrum 16Kb/48Kb
primer_sistema: Spectrum 16Kb/48Kb
Ubicación: El interior de un Z80
Gracias dadas: 248 veces
Gracias recibidas: 104 veces
Contactar:

Re: Space Invasion para ATARI XE/XL

Mensajepor zitror » 20 Mar 2013, 14:28

He de reconocer que personalmente este juego ha sido eclipsado por el Munchkin de MSX pero no quería dejar de reconocer también este excelente trabajo =D>

Salu2 ;)
(C) 1.982 Sinclair Research Ltd

La buhardilla de Zitror

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

Re: Space Invasion para ATARI XE/XL

Mensajepor dancresp » 20 Mar 2013, 15:10

zitror escribió:He de reconocer que personalmente este juego ha sido eclipsado por el Munchkin de MSX pero no quería dejar de reconocer también este excelente trabajo =D>

Salu2 ;)

Ya... :?

De todas formas, ya le comenté a xgipe que queda pendiente una revisión del Munchkin porque no he quedado satisfecho con el resultado... [-(

Ahora, es cierto que el Munchkin ha sido bien recibido. Pero es que se parece tanto... :fantasma:
Buscando la IP de la W.O.P.R.

Avatar de Usuario
xgipe
Atari 1040 STf
Atari 1040 STf
Mensajes: 941
Registrado: 26 May 2010, 15:59
Sistema Favorito: MSX
primer_sistema: MSX
consola_favorita: Sega Master System
Primera consola: Videopac
Ubicación: Ankh-Morpork
Gracias dadas: 88 veces
Gracias recibidas: 69 veces

Re: Space Invasion para ATARI XE/XL

Mensajepor xgipe » 20 Mar 2013, 15:57

Bueno... yo no he comentado nada porque no tengo ningún Atari 8-[ ... Aunque acepto donaciones y tal ... [-o<
BLOAD "CAS:",R
Found: WIN3.11


Volver a “Programación”

¿Quién está conectado?

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