Programando SPACE INVASION para ACORN ELECTRON

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

Programando SPACE INVASION para ACORN ELECTRON

Mensajepor dancresp » 09 Nov 2012, 14:00

SpaceInvasion_2.jpg
SpaceInvasion_2.jpg (81.85 KiB) Visto 4411 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.

Descargar fichero WAV: SpaceInvasion.rar


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.
- Pasar Nivel.
- Perder una vida.
- Presentación.
- Mostrar pantalla de juego.
- Cargar UDG.
- Bloques de gráficos.
- Rutinas varias.


COMO FUNCIONA
Todo el programa ocupa 76 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 y 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.
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 – Refresca la columna de invasores seleccionada.
290 – Bucle que utiliza la variable de sistema “TIME” para que el juego tenga una velocidad constante.
300 – UNTIL que vuelve al REPEAT de la línea 100 si la variable de estado (E) se mantiene a 0.
400 – Rutina de nivel superado (E=2). Se incrementa en 1, pero si estamos en el 4 volvemos al 4.
500 – 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 “” y después de una pausa volvemos a la pantalla de presentación.
2000 – Pantalla de presentación del juego.
2090 – Llamada al sistema operativo 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 – Cargamos los gráficos, redefiniendo los UDG mediante el comando VDU.
3180 – Asignamos los gráficos de los distintos invasores en la matriz (I).
3190 – Asignamos los gráficos del tanque y el búnker en variables.
4000 – PROCEDURE de Pausa, pasando como parámetro el valor correspondiente.
4100 – PROCEDURE para imprimir los valores de Invasores Pendientes “REST” y Munición “AMMO”.
4200 – PROCEDURE para reproducir un sonido.
4300 – PROCEDURE para imprimir la puntuación y el récord.


EL LISTADO

Código: Seleccionar todo

10 DIM T%(5),I$(5),G$(10)
20 GOSUB 3000:GOSUB 2000

100 REPEAT
105 TIME=0:K$=INKEY$(0)
110 IF K$="Z" THEN IF P%>1 THEN P%=P%-1:PRINT TAB(P%*3,22);T$;"   ";
115 IF K$="X" THEN IF P%<5 THEN P%=P%-1:PRINT TAB(P%*3-3,22);"   ";T$;
120 IF K$<>":" THEN GOTO 150 ELSE IF T%(P%)<9 THEN T%(P%)=T%(P%)+1 ELSE T%(P%)=1
140 PRINT TAB(P%*3,20);G$(T%(P%))
150 IF K$<>CHR$(13) OR B%=0 THEN GOTO 200 ELSE A$=I$(P%):B$=STR$(T%(P%)):B%=B%-1:PROCprt_val(4,B%)
160 I%=0:FOR F%=8 TO 1 STEP -1:IF MID$(A$,F%,1)=B$ THEN I%=F%:F%=0:NEXT ELSE NEXT:GOTO 200
165 PROCsound(9000):F%=VAL(B$):IF F%=9 THEN F%=25
170 IF I%=0 THEN GOTO 200 ELSE M%=M%+1:S%=S%+F%:PROCscore(3,S%):IF M%=35 THEN E%=2:GOTO 300
180 IF I%>0 THEN I$(P%)=LEFT$(A$,I%-1)+MID$(A$,I%+1) ELSE I$(P%)=MID$(A$,2)
190 F%=P%:GOTO 250
200 IF W%=11-L% THEN W%=0:PROCsound(50000) ELSE W%=W%+1:GOTO 290
210 F%=RND(5):IF O%>0 THEN I%=RND(9):O%=O%-1:PROCprt_val(6,O%) ELSE I%=0
220 I$(F%)=STR$(I%)+I$(F%):IF MID$(I$(F%),8,1)>"0" THEN E%=1
250 Z%=F%*3:FOR I%=1 TO 7+E%:N%=VAL(MID$(I$(F%),I%,1)):VDU 31,Z%,I%*2+2:PRINT G$(N%):NEXT
290 REPEAT UNTIL TIME>15
300 UNTIL E%<>0
310 IF E%=1 THEN GOTO 500

400 FOR N%=1 TO 5:PROCsound(N%*100):PROCpause(500):NEXT:L%=L%+1:IF L%=6 THEN L%=4
410 PRINT TAB(33,10);L%:GOSUB 2500:GOTO 100

500 FOR F%=1 TO 20:PROCsound(F%*1000):NEXT:PROCpause(3000)
510 IF V%=1 THEN GOTO 550 ELSE V%=V%-1:PRINT TAB(1,24);STR$(V%);" ";
520 IF V%>1 THEN FOR F%=2 TO V%:PRINT T$;:NEXT
530 PRINT "  ";:GOSUB 2500:GOTO 100
550 PRINT TAB(14,24);"<GAME OVER>";:PROCpause(20000):IF S%>R% THEN R%=S%
560 GOSUB 2000:GOTO 100

2000 CLS:PRINT TAB(1,1);"SCORE<1>       HI-SCORE       SCORE<2>"
2020 PROCscore(3,S%):PROCscore(18,R%)
2030 PRINT TAB(18,5);"PLAY";TAB(13,7);"SPACE INVASION"
2040 PRINT TAB(9,11);"*SCORE ADVANCE TABLE*":PRINT
2050 FOR F%=1 TO 4:PRINT TAB(7);G$(F%);"=";STR$(F%);" POINTS * ";
2060 PRINT G$(F%+4);"=";STR$(F%+4);" POINTS":PRINT:NEXT
2070 PRINT TAB(14);G$(9);"=25 POINTS":PRINT TAB(1,23);STRING$(38,"_")
2080 PRINT TAB(1,24);"3 ";T$;T$;TAB(30,24);"CREDIT 00";
2090 OSCLI "FX 15,1":F%=GET:FOR F%=4 TO 22:PRINT TAB(1,F%);STRING$(38," "):NEXT

2100 PRINT TAB(24,4);"* AMMO : 50";TAB(24,6);"* REST : 35";TAB(24,10);"* LEVEL: 1"
2110 PRINT TAB(24,15);"* KEYS:";TAB(24,17);" Z  : LEFT";TAB(24,18);" X  : RIGHT"
2120 PRINT TAB(24,19);"RTN : FIRE";TAB(24,20);" *  : CHANGE"
2300 L%=1:V%=3:S%=0:PROCscore(3,S%)
2500 FOR F%=1 TO 5:T%(F%)=1:I$(F%)="00000000":NEXT
2510 FOR F%=1 TO 14:PRINT TAB(1,F%+3);:VDU 252:PRINT STRING$(16," ");:VDU 252:NEXT
2520 PRINT:PRINT "   "+C$+C$+C$+C$+C$;TAB(3,22);"      ";T$;"      "
2540 PRINT TAB(1,20);"> "+G$(1)+" "+G$(1)+" "+G$(1)+" "+G$(1)+" "+G$(1)+" <"
2550 P%=3:W%=0:E%=0:O%=35:M%=0:B%=50:PROCprt_val(4,B%):PROCprt_val(6,O%)
2560 RETURN

3000 VDU 23,224,0,0,0,0,0,0,0,0:VDU 23,225,0,0,0,0,0,0,0,0
3020 VDU 23,226,1,3,7,16,15,5,8,4:VDU 23,227,128,192,224,176,240,160,16,32
3030 VDU 23,228,8,4,15,27,63,63,40,6:VDU 23,229,32,64,224,176,248,248,40,192
3040 VDU 23,230,3,31,63,57,63,14,25,12:VDU 23,231,192,248,252,156,252,112,152,48
3050 VDU 23,232,3,7,13,15,6,3,4,2:VDU 23,233,192,224,176,240,96,192,32,64
3070 VDU 23,234,1,3,7,13,15,2,5,10:VDU 23,235,128,192,224,176,240,64,160,80
3080 VDU 23,236,8,36,47,59,63,31,8,16:VDU 23,237,32,72,232,184,248,240,32,16
3090 VDU 23,238,3,31,63,57,63,6,13,48:VDU 23,239,192,248,252,156,252,96,176,12
3100 VDU 23,240,3,7,13,15,6,3,2,4:VDU 23,241,192,224,176,240,96,192,64,32
3110 VDU 23,242,0,7,31,63,109,255,57,16:VDU 23,243,0,224,248,252,182,255,156,8
3120 VDU 23,246,1,3,3,127,255,255,255,255:VDU 23,247,0,128,128,252,254,254,254,254
3140 VDU 23,250,31,63,127,255,255,252,248,248:VDU 23,251,248,252,254,255,255,63,31,31
3150 VDU 23,252,60,36,60,24,24,60,36,60
3180 I%=0:FOR F%=224 TO 242 STEP 2:G$(I%)=CHR$(F%)+CHR$(F%+1):I%=I%+1:NEXT
3190 T$=CHR$(246)+CHR$(247):C$=CHR$(250)+CHR$(251)+" ":R%=0
3200 RETURN

4000 DEF PROCpause(I%)
4010 FOR F%=1 TO I%:NEXT F%
4020 ENDPROC

4100 DEF PROCprt_val(F%,I%)
4110 PRINT TAB(33,F%);STR$(I%);" "
4120 ENDPROC

4200 DEF PROCsound(I%)
4210 SOUND 1,-15,I%,1
4220 ENDPROC

4300 DEF PROCscore(F%,I%)
4310 PRINT TAB(F%,2);RIGHT$("0000"+STR$(I%),4)
4320 ENDPROC



APUNTES FINALES
La principal dificultad del juego ha consistido en conseguir una velocidad constante de ejecución y una respuesta del teclado fiable. Afortunadamente este sistema nos facilita mucho la tarea.

Los gráficos del juegos son de 16x8, pero se han conseguido redefiniendo los caracteres de 8x8. En este sistema este proceso es muy rápido teniendo en cuenta la cantidad de gráficos que se han redefinido.

Para la pantalla de presentación me he basado en la del juego “SPACE INVADERS”. La forma de presentación es distinta ya que aquí se muestra todo de golpe y no letra a letra.

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

El ELECTRON permite leer el teclado de varias formas distintas:
1) Se consulta el estado de la tecla justo en ese momento.
2) Se lee una tecla del buffer de teclado.
3) Se espera “n” centésimas de segundos a que se pulse una tecla.
4) El sistema espera que se pulse una tecla antes de continuar.

Para este juego he usado el segundo método porque nos ofrece una fiabilidad total, ya que siempre se procesan todas las teclas que se han pulsado en el orden en que se han pulsado. El resultado es perfecto y para este juego es básico.

El “OSCLI FX 15,1” hace una limpieza del buffer del teclado mediante una llamada al sistema operativo. Esta es otra de las características del BASIC de los ACORN. Todos los comandos del sistema operativo pueden ser ejecutados desde el programa en BASIC, sin necesidad de usar el ensamblador.

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. También he usado el método REPEAT/UNTIL ya que el manual indica que es más rápido que el bucle FOR/NEXT. También he usado el método de usar, siempre que sea posible, variables enteras (con %) ya que la velocidad es algo superior.

En la línea 250 he usado el método VDU 31,X,Y que hace exactamente lo mismo que el TAB(X,Y) pero más rápido.

Para que la velocidad sea constante, teniendo en cuenta que hay veces que se ejecutan más líneas que otras, inicializo la variable TIME en la línea 105, y después de todo el proceso, inicio en la línea 290 un bucle REPEAT/UNTIL que comprueba que hayan pasado 15/100 segundos desde la ejecución de la línea 100. Con esto conseguimos que la velocidad de ejecución sea constante. Y se ha conseguido.

Para el tema de sonido, en el que sigo siendo un perfecto inútil, he usado el comando SOUND mediante el PROCEDURE de la línea 4200. Simplemente paso un valor como parámetro y se reproduce un sonido.

Como apunte final, me ha encantado programar este juego en el ELECTRON. Su teclado es excelente. Agradable, fiable y muy retro. Hay que tocarlo para entenderlo. Su BASIC es muy potente y rápido, permitiendo acceder a múltiples características de sus sistema operativo de una forma muy sencilla. En este juego no he usado su ensamblador integrado, lo que le confiere una potencia única. En definitiva, un equipo muy recomendable.

Y como siempre…

Para terminar, todo este desarrollo se ha programado en un ACORN ELECTRON auténtico.

Os invito a probarlo.

SpaceInvasion_1.jpg
SpaceInvasion_1.jpg (106.53 KiB) Visto 4411 veces

SpaceInvasion_2.jpg
SpaceInvasion_2.jpg (81.85 KiB) Visto 4411 veces
Buscando la IP de la W.O.P.R.

Avatar de Usuario
radastan
Amiga 2500
Amiga 2500
Mensajes: 4542
Registrado: 11 Jun 2007, 19:29
Sistema Favorito: Spectrum 16Kb/48Kb
primer_sistema: Spectrum 16Kb/48Kb
consola_favorita: Sega Genesis/Megadrive
Primera consola: TV Games/Pong Clone
Ubicación: Córdoba
Gracias dadas: 9 veces
Gracias recibidas: 40 veces
Contactar:

Re: Programando SPACE INVASION para ACORN ELECTRON

Mensajepor radastan » 09 Nov 2012, 14:50

Como me molan estos hilos, se echa mucho en falta que la gente le de una oportunidad al BASIC y haga cosas así.
Yo tengo una máquina del tiempo, se llama ZX Spectrum, siempre me devuelve a los buenos momentos.
(\.../) (\.../) (\.../) (\.../)
( *.*) ('.'= ) ('.'= ) ('.'= )
(")_(") (")_(") (")_(") (")_(")
╔═══╦═══╦═══╦══╦══╗
║╔═╗║╔═╗║╔═╗╠╣╠╩╣╠╝
║║─║║╚══╣║─╚╝║║─║║
║╚═╝╠══╗║║─╔╗║║─║║
║╔═╗║╚═╝║╚═╝╠╣╠╦╣╠╗
╚╝─╚╩═══╩═══╩══╩══╝

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: Programando SPACE INVASION para ACORN ELECTRON

Mensajepor xgipe » 09 Nov 2012, 14:58

Impecable, como de costumbre. Dancresp rules the BASIC... :D
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 7 invitados