Fungaloids - SHARP MZ-700

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

Fungaloids - SHARP MZ-700

Mensajepor dancresp » 23 Mar 2013, 08:44

DSC_1008.jpg
DSC_1008.jpg (61.81 KiB) Visto 4237 veces


EL JUEGO
El juego original se publico en el año 1982 y fue programado en un ZX-81.

El objetivo del juego consiste en destruir los Fungaloids antes que lleguen a la parte superior de la pantalla.

Estas plantas crecen, y disparan unas esporas que nos destruyen si nos alcanzan. La misma suerte corremos si chocamos con ellos o los distintos enemigos que hay en la zona de juego.

Nuestra única nave tiene una capacidad limitada de combustible y munición, y periódicamente debemos repostar en las zonas correspondientes.

Al destruir todos los segmentos de los Fungaloids pasamos de nivel, ganamos 100 puntos y aumenta la dificultad.

Cerca de la base de algunos fungaloids hay unas bolas blancas. Si destruimos una, perdemos 20 puntos. Si nos quedamos sin puntos finaliza el juego.


BLOQUES
He dividido el listado en 11 bloques:

- Declaración de matrices e inicio del juego.
- Control de nuestra nave.
- Mover enemigos.
- Control del disparo.
- Control del proyectil enemigo.
- Final del Juego.
- Pasar Nivel.
- Presentación.
- Mostrar pantalla de juego e inicializar variables.
- Rutinas varias.
- Bloque de datos.


COMO FUNCIONA
Todo el programa ocupa 84 líneas.

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

10 - Definimos las matrices del juego.
110 - Leemos las teclas y si no se ha pulsado una tecla de los cursores salta a 170.
110 - Usamos un ON GOTO para comprobar si hay que mover la nave. En caso de movimiento vertical, controlamos la altura y posición para ir a las rutinas de repostar combustible (4100) ó munición (4200).
160 – Antes de mover borramos la nave, y antes de volverla a poner miramos que hay debajo. Si hay algo se salta a 600.
200 - Código que decide que enemigo hemos de mover: 0- Barrera de energía, 1- Naves enemigas, 2- Fungaloids y 3- Nada.
210 - Rutina de movimiento de la barrera de energía.
230 - Rutina de movimiento de una de las tres naves.
260 - Rutina de movimiento de uno de los seis Fungaloids.
300 - Control de nuestro disparo.
400 - Control de disparo del Fungaloid.
450 - Miramos los 3 caracteres que hay en la posición de nuestra nave. Si no corresponden a la nave (suma distinta de 182) significa que hemos chocado con algo y salta al final del juego, sino se vuelve al principio del bucle.
600 - Final de partida.
700 - Pasar nivel.
900 – Rutina para imprimir nuestra nave en la posición correspondiente.
2000 - Pantalla de presentación.
2500 - Dibujamos la zona de juego.
3000 - Inicializamos las variables del juego.
4000 - Subrutina que espera a que se pulse una tecla.
4100 - Subrutina para repostar combustible.
4200 - Subrutina para repostar munición.
9000 - Datos de las posiciones iniciales verticales de los 6 Fungaloids.


EL LISTADO

Código: Seleccionar todo

     ' Declaración de matrices, variables e inicio del juego
  10 DIM E(6),P(6),V(3),H(6)
  20 G1$=CHR$(241):G2$=CHR$(112):G3$=CHR$(225):G4$=CHR$(204)
  30 N$=CHR$(215)+G4$+CHR$(215):TEMPO 7
  50 GOSUB 2000

     ' Control de nuestra nave
 100 GET K$:K=ASC(K$)-16:IF (K<1)+(K>4) THEN 170
 110 CURSOR X,Y:PRINT "   ":ON K GOTO 120,130,140,150
 120 IF Y+1<DY THEN Y=Y+1:A=A+40
 122 IF Y<>18 THEN 160
 124 IF X<5 THEN GOSUB 900:GOTO 4100
 126 IF X>33 THEN GOSUB 900:GOTO 4200
 128 GOTO 160
 130 IF Y>1 THEN Y=Y-1:A=A-40
 135 GOTO 160
 140 IF X<36 THEN X=X+1:A=A+1
 145 GOTO 160
 150 IF X>1 THEN X=X-1:A=A-1
 160 IF PEEK(A)+PEEK(A+1)+PEEK(A+2)<>0 THEN GOSUB 900:GOTO 600
 170 GOSUB 900:C=C-1:CURSOR 7,22:PRINT [0,7] USING "###";C;:IF C<=0 THEN 600

     ' Mover enemigos
 200 ON RND(1)*4 GOTO 230,260,300
 210 IF RND(1)>.4 THEN IF M>1 THEN M=M-1:CURSOR 33,M:PRINT [6,2] "M":GOTO 300
 220 IF M<16 THEN CURSOR 33,M:PRINT " ":M=M+1
 225 GOTO 300
 230 N=RND(1):F=INT(1)*3)+1:CURSOR 8+F*5,V(F):PRINT " "
 240 V(F)=V(F)+((N<.5)*(V(F)<16))-((N>=.5)*(V(F)>0))
 250 CURSOR 8+F*5,V(F):PRINT [2,] "#":GOTO 300
 260 F=INT(RND(1)*L)+1:IF F>6 THEN 300
 270 T=T+1:P(F)=P(F)-1:CURSOR F*5+1,P(F):PRINT [4,] G1$:IF P(F)=0 THEN 600

     ' Control de nuestro disparo
 300 IF D>0 THEN 330
 310 IF (K$<>" ")+(B=0) THEN 400
 320 IF D=0 THEN DY=Y:DX=X+1:D=A+1:B=B-1:CURSOR 31,22:PRINT [0,7] USING "##",B:MUSIC "A1"
 330 IF DY>Y THEN CURSOR DX,DY:PRINT " "
 335 DY=DY+1:D=D+40:F=PEEK(D):IF F=0 THEN 375
 340 D=0:IF F=74 THEN S=S-20:MUSIC "#C7":GOTO 355
 345 IF F<>208 THEN DY=99:GOTO 400
 350 T=T-1:S=S+1:F=(DX-1)/5:P(F)=P(F)+1:IF O=0 THEN O=2
 355 CURSOR DX,DY:PRINT " ":CURSOR 17,22:PRINT [0,7] USING "######";S:DY=99
 360 IF S<0 THEN 600
 365 IF T=0 THEN 700
 370 GOTO 400
 375 CURSOR DX,DY:PRINT [0,] G2$

     ' Control disparo Fungaloid
 400 IF O=0 THEN 450
 410 IF O=2 THEN O=1:X1=F*5+1:Y1=E(F):F1=F
 420 CURSOR X1,Y1:A$=" ":C1=1:IF Y1>=P(F1) THEN A$="x":C1=4
 430 PRINT [C1,] A$:IF Y1=0 THEN O=0:GOTO 450
 440 Y1=Y1-1:CURSOR X1,Y1:PRINT [4,] G3$
 450 IF PEEK(A)+PEEK(A+1)+PEEK(A+2)=182 THEN 100

     ' Final de partida
 600 CURSOR 15,11:PRINT [7,2] " GAME OVER ":MUSIC "G3FEDC":GOSUB 4000:GOTO 50

     ' Pasar nivel
 700 CURSOR 15,11:PRINT [0,4] " WELL DONE ":GOSUB 4000
 710 IF L>15 THEN L=L-5
 720 MUSIC "B3ABAB":S=S+100:GOSUB 2500:GOTO 100

     ' Imprimir nuestra nave
 900 CURSOR X,Y:PRINT [6,] N$:RETURN

     ' Presentación
2000 CLS:PRINT:PRINT [7,0] TAB(15);"FUNGALOIDS"
2010 PRINT:PRINT " THEN FUNGALOIDS ARE GROWING AND WHEN"
2015 PRINT " THEY REACH THE SKY THEY PRODUCE DEADLY"
2020 PRINT " SPORES. YOU MISSION IS TO DESTROY THE"
2025 PRINT " FUNGALOIDS BY DROPPING ANTI-FUNGUS"
2030 PRINT " BOMBS ON THEM.":PRINT:PRINT [70] TAB(8) " PRESS ANY KEY TO START "
2035 PRINT:PRINT TAB(9) "(C) SCAINET SOFT, 2013"
2040 GOSUB 2500:GOSUB 900:POKE $59,$53:GOSUB 4000:S=0:L=50:POKE $59,$F0:CLS

     ' Mostrar zona de juego
2500 CURSOR 28,17:PRINT [0,] "/xxx"
2510 PRINT [0,] TAB(23);"  /xxxxxxxx"
2520 PRINT [0,] TAB(21);"xxxxxxxxxxxxx"
2530 PRINT [0,] "xxxxxx       /\    xxxxxxxxxxxxxxxxxxxxx";
2540 PRINT [0,] "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
2550 PRINT [0,7] "x9000xx500xxxxxxx000000xxxxxxxx30xx1000x"
2560 CURSOR 17,20:PRINT [0,7] G4$+G4$:CURSOR 23,18:PRINT [0,7] G4$
2570 CURSOR 29,16:PRINT [0,7] G4$
2580 CURSOR 0,19:PRINT [6,0] "  //  ":CURSOR 34,19:PRINT [6,0] "  ++  "
2590 CURSOR 0,21:PRINT [6,0] " FUEL ":CURSOR 34,21:PRINT [6,0] " BOMB "

     ' Inicializar variables del juego
3000 RESTORE 9000:FOR F=1 TO 6:READ E(F):P(F)=E(F)-3:H(F)=F*5+1
3010 FOR I=P(F) TO P(F)+3:CURSOR H(F),I:PRINT [4,] "x":NEXT I:NEXT F
3020 M=18:X=1:Y=13:A=53769:C=500:B=30:D=0:T=24:TB=1000:TC=9000:DY=99
3030 V(1)=9:V(2)=12:V(3)=6:O=0:RETURN

     ' Rutina: Pulsar "RETURN"
4000 GET A$:IF A$<>CHR$(13) THEN 4000
4010 RETURN

     ' Rutina: Recargar combustible
4100 FOR F=1 TO 14 STEP .02:CURSOR 1,20:PRINT [0,7] MID$("xxxx  /o\   xxxx",F,4)
4110 NEXT F:IF TC<500 THEN C=TC:F=C:GOTO 4130
4120 F=500-C:C=500
4130 TC=TC-F:CURSOR 1,22:PRINT [0,7] USING "####xx###";TC;C:GOTO 200

     ' Rutina: Recargar munición
4200 FOR F=1 TO 14 STEP .02:CURSOR 35,20:PRINT [0,7] MID$("xxxx  ooo   xxxx",F,4)
4210 NEXT F:IF TB<30 THEN B=TB:F=B:GOTO 4230
4220 F=30-B:B=30
4230 TB=TB-F:CURSOR 31,22:PRINT [0,7] USING "##xx####";B;TB:GOTO 200

     ' Datos de posición inicial vertical de los Fungaloids
9000 DATA 20,20,20,19,17,16


Atención gráficos:
En ciertas partes he guardado el gráfico en una variable, pero en otras no he podido.
Indico que gráficos van en ciertas partes:

2500-2550: Sustituir “x” por el gráfico de la tecla “F”, con SHIFT pulsado. El bloque oscuro.
2500-2550: Sustituir “/” por el gráfico de la tecla “]}”, sin SHIFT. El triangulo.
2500-2550: Sustituir “\” por el gráfico de la tecla “:*”, con SHIFT pulsdo. El triangulo.
4100: sustituir el “/o\” por los gráficos de “K” con SHIFT, “D” sin SHIFT y “K” sin SHIFT.
4200: sustituir el “ooo” por tres gráficos de “D” sin SHIFT.


APUNTES FINALES
La verdad es que la velocidad de este equipo me ha sorprendido. El BASIC se debe cargar de cinta porque este sistema solo tiene un sencillo programa monitor al arrancar, pero pasados los dos minutos de carga el BASIC no defrauda. En general.

La principal diferencia de esta versión respecto a la original del ZX-81 o del MSX es que funciona en modo 40 columnas y no 32. Lo he solucionado ampliando un poco las bases de recarga y separando los Fungaloids con un carácter extra.

Este sistema no permite redefinir los gráficos con lo que he tenido que aprovechar toda la variedad de gráficos existentes. Hay varios juegos alternativos de caracteres que dan bastantes posibilidades, pero en este caso me he limitado a los básicos.

El bucle principal se repite hasta que perdemos la única vida de que disponemos, de todas formas, en cada pasada solo movemos uno de los enemigos, que se selecciona de forma aleatoria. Al hacerlo así hemos conseguido que el bucle se repita varias veces por segundo con lo que le da sensación de fluidez.

En cada pasada decidimos, mediante un ON GOTO, que enemigo se ha de mover:
0) Aleatoriamente hacemos subir o bajar la barrera de energía.
1) Aleatoriamente hacemos subir o bajar una de las tres naves.
2) En el caso de los Fungaloids, calculamos un número aleatorio grande. Si es inferior a 7, hacemos crecer el Fungaloid correspondiente, pero si es mayor de 6 no hacemos nada. Esto hace que crezcan más lentamente, pero al ir avanzando en el juego, el número que calculamos disminuye y por consiguiente, aumenta su velocidad de crecimiento, y es más difícil.
3) Esta opción no estaba en la versión MSX, pero aquí la he puesto para frenar un poco a los enemigos. Sino es muy rápido.

Para detectar colisiones, utilizo unas variables que indican la posición absoluta en la memoria de pantalla sobre la que está el ala izquierda de nuestra nave, o nuestro disparo. Accediendo a la memoria de video con un PEEK podemos ver que estamos tocando. Esto nos ahorra muchos cálculos, y es muy preciso.

En el juego original, al sobrevolar un Fungaloid nos disparaba. Aquí, para ganar velocidad he optado por hacer que nos dispare al destruir un fragmento de Fungaloid. Así aprovecho el mismo código que me indica que Fungaloid he alcanzado para poner su disparo en la planta correspondiente.

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

La verdad es que me habría gustado realizar algunas modificaciones, pero he optado por mantener el espíritu del juego original, y a pesar de estar programado completamente en BASIC, el juego ha conseguido una velocidad muy decente, y se deja jugar perfectamente. Eso si, mi cruz sigue siendo el sonido.

Respecto al BASIC de este equipo:
- Como no reside en ROM se podría haber usado otras versiones que hay disponibles.

- Este equipo no distingue entre distintos tipos de variables numéricas, y todas se tratan como variables en coma flotante.

- Sorprendentemente este BASIC no tiene ni OR ni AND, pero lo han resuelto de una forma muy original: el “OR” se ha sustituido por un “+” y el “AND” por un “*”, con las condiciones entre paréntesis.

El funcionamiento es lógico:
Al hacer un IF el sistema resuelve las condiciones y devuelve un 0 si el sistema es FALSO (False) o un valor distinto de 0 (varía según el sistema) que indica que es VERDADERO (True).

Así:
A=10
B=20
IF (A<B AND A=10) THEN ... Se cumple la condición porque devuelve un (1 AND 1 ) que da como resultado un 1.

En el MZ-700:
IF (A<B)*(A=10) THEN ... Si todas las condiciones dan 1 el resultado de las multiplicaciones será distinto de 0 y se cumplirá la condición. Solo que haya un 0 el resultado será 0 y no se cumplirá la condición.

Con el “OR” pasa lo mismo, pero solo que una condición devuelva un valor distinto de 0 ya se cumplirá la condición.

Lo dicho, muy original.

- Respecto a los PRINT, tiene una forma muy simple y cómoda de hacerlo asignando el color a la vez que lo muestras.

- Este BASIC tampoco permite los ELSE con lo que hay que usar más líneas de código, pero como digo, es muy rápido.

- Uno de los problemas que más me ha costado solucionar ha sido la no auto-repetición de las teclas. A base de revisar juegos de acción en BASIC pude ver que con POKE $59,$F0 se activa la auto-repetición de las teclas y con POKE $59,$53 se desactivo. Esto lo hago en la línea 2040.

- Para controlar colisiones u otras cosas debes acceder a la memoria de vídeo, que está en la RAM principal.

- Y con respecto al sonido, es bastante limitado pero no tanto como yo.

En resumen, es un señor equipo, grande, con un buen teclado y un excelente casete.
Durante su uso muchas veces tienes la sensación de estar usando un MSX, pero ni de lejos tiene las mismas prestaciones.


Y como siempre…

Para terminar, todo este desarrollo se ha programado en un SHARP MZ-700 real.


Os invito a probarlo.

DSC_1007.jpg
DSC_1007.jpg (97.14 KiB) Visto 4237 veces

DSC_1011.jpg
DSC_1011.jpg (50.81 KiB) Visto 4237 veces

DSC_1012.jpg
DSC_1012.jpg (52.96 KiB) Visto 4237 veces

DSC_1014.jpg
DSC_1014.jpg (63.99 KiB) Visto 4237 veces

DSC_1015.jpg
DSC_1015.jpg (149.01 KiB) Visto 4237 veces

DSC_1019.jpg
DSC_1019.jpg (109.91 KiB) Visto 4237 veces
Última edición por dancresp el 23 Mar 2013, 20:07, editado 1 vez en total.
Buscando la IP de la W.O.P.R.

Avatar de Usuario
alt
Amiga 2500
Amiga 2500
Mensajes: 4416
Registrado: 07 Sep 2004, 21:52
Ubicación: madrid
Gracias dadas: 1251 veces
Gracias recibidas: 2246 veces
Contactar:

Re: Fungaloids - SHARP MZ-700

Mensajepor alt » 23 Mar 2013, 12:34

¿Sabes que probablemente acabas de hacer uno de los juegos más divertidos para MZ-700? :-D

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: Fungaloids - SHARP MZ-700

Mensajepor dancresp » 23 Mar 2013, 20:07

alt escribió:¿Sabes que probablemente acabas de hacer uno de los juegos más divertidos para MZ-700? :-D

Hombre, en ensamblador tiene juegos que están más que bien, pero en BASIC no se que hay.

Eso si, yo me he divertido mucho haciéndolo.

Por cierto, he modificado la ficha porque me había dejado de comentar como he solucionaado el tema de la auto-repetición del teclado.
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 7 invitados