High Score

"Conocer los mecanismos ocultos y los patrones de conducta de los enemigos de un juego como Pac-man o Space Invaders, hace posible alcanzar la máxima puntuación. Si eso ocurre tu nombre aparecerá en las pantallas de tu juego favorito, como hacía el creador de Paranoides Espaciales, Kevin Flynn en su sala Arcade".

ENDGAME

EngineZX se encarga de gestionar SCORE y HIGHSCORE después de que el juego termina con el comando ENDGAME. Actualiza el High Score cuando SCORE es mayor que HIGHSCORE. Pac-man muestra nuestro "récord" en el marcador inferior derecho.

Desde la última versión del MPAGD el juego comienza de nuevo automáticamente, poniendo a cero el marcador de puntos de la izquierda. Esto es correcto y debería ser suficiente.

Ensamblador

Nos adentramos voluntariamente en una parte del programa instructiva y entretenida si te gustan los retos. El juego ya recuerda el último "récord" de tus partidas. Ahora bien, si quieres imitar los marcadores de las máquinas Arcade de las salas de juegos, necesitas implementar el High Score.

La última versión del EngineZX incluye el código siguiente, que te da la opción de salir a BASIC o reiniciar el juego automáticamente.

; if you wish to exit to BASIC at the end of each game, change "jp gamelp" to "jp game".
       jp gamelp           ; start the game.

Por defecto el juego ejecuta un bucle infinito, a no ser que cambies la instrucción "jp gamelp" por la otra instrucción "jp game", no regresa al sistema BASIC como hacía en versiones anteriores. No toques nada por ahora, lo haremos de manera automática más adelante. 

Esta instrucción está escrita en lenguaje ensamblador que posteriormente se traduce a código máquina Z80, que es el lenguaje de 8bits que entiende el ZX Spectrum. El High Score será un programa escrito en BASIC. Si ¿Cómo lo ves?.

Salir a BASIC

EngineZX ejecuta lo siguiente después de jugar y cuando "todo está terminado":

tidyu0 ld hl,10072         ; BASIC likes this in alternate hl.
       exx                 ; flip hl into alternate registers.
       ld bc,score         ; return pointing to score.
       ret

En otra parte del código ensamblador del EngineZX se encuentran:

score  defb '000000'       ; player's score.
hiscor defb '000000'       ; high score.
bonus  defb '000000'       ; bonus.

Aclararte que tidyu0, score, hiscor y bonus son etiquetas que apuntan a direcciones de memoria.
 
El programa EngineZX carga en el "registro bc" la dirección score (score es una etiqueta) apuntando al marcador del jugador y regresa (o sale a BASIC en nuestro caso).

Los registros en ensamblador son como las variables en otros lenguajes, para representar una dirección de memoria necesitamos un número de 16 bits o una pareja de registros de 8 bits; como por ejemplo el "registro bc". Hemos aprendido algo de ensamblador, ¿qué te parece?

Esto es práctica bastante común en los programas de código máquina. Si EngineZX.asm es considerada una función, ésta devuelve un valor de 16 bits recogido en el registro bc. Esto es lo que vamos a usar en nuestro programa High Score que está escrito en BASIC mediante el siguiente comando:

80 LET R = USR 32000
90 LET D = R : LET a$ = ""
100 FOR f = 0 TO 5
110 LET a$ = a$ + CHR$ PEEK (D + f)
120 NEXT f
130 LET M = VAL a$

El programa recibe el valor del registro "bc" en la variable R llamando al EngineZX que reside en la dirección de memoria 32000 mediante la función USR. Después reconstruye los 6 dígitos del Score almacenados en esa dirección uno por uno en la variable a$. Por último almacenamos su valor en la variable M.

BASIC

Este es el listado del programa completo:

5 CLEAR VAL "31999"
10 LOAD "SC"SCREEN$: POKE 23739,111
20 LOAD "AG"CODE 32000
30 INK 7: PAPER 0: BORDER 0
40 LET H = 0: LET S = 0: DIM h$(6,11)
50 FOR f = 1 TO 5
60 LET h$(f) = "AAA  000000"
70 NEXT f
80 LET R = USR 32000
90 LET D = R : LET a$ = ""
100 FOR f = 0 TO 5
110 LET a$ = a$ + CHR$ PEEK (D + f)
120 NEXT f
130 LET M = VAL a$
200 CLS
300 FOR i = 1 TO 5
310 IF M = VAL h$(i,6 TO) THEN GO TO 650 
330 IF i = 6 THEN GO TO 650
340 IF M < VAL h$(i,6 TO) THEN NEXT i
405 PRINT AT 3, 9; "NUEVO RECORD!"
430 FOR j = 5 TO i STEP -1
440 LET h$(j+1) = h$(j)
450 NEXT j
510 LET b$="   " : LET n = 65: LET x = 1
520 GO SUB 800
570 PRINT AT (5 + i*2),10; b$ + "  " + a$
572 PRINT AT (5 + i*2),x+9; OVER 1; CHR$(143)
575 LET k$ = INKEY$: IF k$ = "" THEN GO TO 575
580 IF k$ = "w" AND n < 90 THEN LET n = n + 1: LET b$(x) = CHR$ (n)
585 IF k$ = "s" AND n > 65 THEN LET n = n - 1: LET b$(x) = CHR$ (n)
595 IF k$ = "a" AND x > 1 THEN LET x = x - 1
600 IF k$ = "d" AND x < 3 THEN LET x = x + 1
610 IF k$ = " " THEN LET h$(i) = b$ + "  " + a$: GO TO 650
620 BEEP .05,0 : GO TO 570
650 PRINT AT 3, 9; " MARCADORES  ": GO SUB 800
655 FOR f = 1 TO 500
660 IF INKEY$ <> "" THEN GO TO 80
670 NEXT f 
680 GO TO 80
810 FOR f = 1 TO 5
820 PRINT AT (5 + f*2),10; INK f; h$(f)
840 NEXT f
850 RETURN

El programa consta de dos partes. La primera es el cargador del juego y la segunda gestiona los marcadores.
No está comentado para que ocupe lo mínimo posible. La línea 5 limita la memoria destinada al usuario (RAMTOP) hasta la dirección 31999 justo antes de que empiece el espacio reservado para el Juego. La línea 10 es el cargador. La línea 40 establece las variables iniciales. La línea 80 ejecuta el juego recogiendo Score a su regreso. Después se gestionan los marcadores. En línea 650 se presentan los marcadores, hace una pausa y salta al Juego otra vez. Las teclas que yo uso son "w a s d" para mover y "espacio" para FIRE1, podrás definir las que tu has escogido en el juego.

Gracias a este lenguaje de programación muchos y muchas pasamos horas de entretenimiento y desarrollo creativo. Es la razón por la que debemos incluir este pequeño programa en el proyecto Pacman.

MEMORIA

La RAM del ZX Spectrum se localiza entre la dirección de memoria 16384 (4000 hexadecimal) y 65535 (FFFF hexadecimal). Esta memoria no está a la disposición del usuario en exclusiva, debe compartirla con el ZX Spectrum para que éste pinte la pantalla, almacene variables, etc. El editor MPAGD coloca al juego en la dirección 24832, la más baja posible para poder cargar el juego desde BASIC. El cargador minimalista que construye el editor MPAGD es el siguiente:

10 CLEAR VAL "24063": CLS: LOAD "" CODE: RANDOMIZE USR VAL "24064"

Nosotros necesitamos más memoria para el programa de marcadores BASIC. Vamos desplazar al juego un poco más arriba en memoria, en concreto a la dirección 32000 para hacerle sitio. Habrá que hacer Modificaciones en el MPAGD para lograrlo.

Build

Vamos a modificar todo esto de forma automática. Descarga este archivo LoaderMod en el directorio Suite ZX de tu MPAGD. Descomprime ahí mismo el contenido, modificarás el archivo Build.bat y crearás varios directorios para lograr los cambios que queremos. El programa build.bat quedará así:

@echo off
cls
rem ------------------------------------------------------
rem 0 = Standard MPAG
rem 1 = Modificaciones para Pac-man
rem ------------------------------------------------------
set mod=1
rem cambia el nombre para tu juego
set gamename=Pacman48
rem ------------------------------------------------------

rem Compile AGD file
copy AGDsource\%1.agd AGD
cd AGD
CompilerZX %1
rem Assemble game
if %mod% == 0 (
copy %1.asm ..\sjasmplus\
copy ..\..\user.asm ..\sjasmplus\
del %1.*
cd ..\sjasmplus
copy leader.txt+%1.asm+trailer.txt agdcode.asm
sjasmplus.exe agdcode.asm --lst=list.txt
copy test.tap ..\speccy

rem limpieza en sjasmplus
del %1.asm
del user.asm
del agdcode.asm
del test.tap

rem Start emulator
cd ..\speccy
speccy -128 test.tap
del test.tap
cd ..
)
if %mod% == 1 (
@echo Modificaciones para Pac-man
copy %1.asm ..\assembly\
copy ..\..\user.asm ..\assembly\
del %1.*
cd ..\assembly
copy ..\Basic\loader48k.bas ..\assembly\
copy ..\Tapes\SC.tap ..\assembly\
..\Tools\bas2tap -e -a1 -s%gamename% loader48k.bas loader48k.tap
..\Tools\fart %1.asm 24832 32000
..\Tools\fart %1.asm "jp gamelp " "jp game"
..\Tools\Pasmo --tap --name AG %1.asm AG.tap
copy /b loader48k.tap + SC.tap + AG.tap %gamename%.tap
rem limpieza en assembly
del %1.asm
del user.asm
del loader48k.*
del AG.tap
del SC.tap

rem Start emulator
..\speccy\speccy -128 %gamename%.tap
cd ..
) 

Arriba el comando "set mod=0" establece el modo de trabajo que venimos haciendo hasta ahora, siempre puedes usarlo.
Pero con la opción "set mod=1" ahora añadimos el cargador, una pantalla ("screen") para mostrar cuando la cinta está cargando, cambiamos la dirección de memoria del juego a 32000, cambiamos el comando "jp gamelp" por "jp game" y montamos una cinta "Pacman48.tap" con el cargador "loader48" la presentación "SC" y el código del juego "AG".

El archivo build.bat te permite ver cómo trabaja el MPAGD para construir las cosas. CompilerZX.exe compila los scripts que hemos trabajado estas semanas que junto con EngineZX.asm generan el juego. Después un programa ensamblador (sjasmplus.exe o Pasmo.exe) generan las cintas para poder jugar en tu ZX Spectrum.

Ahora es buen momento para editar el ..\Suite ZX\Basic\loader48k.bas para cambiar las teclas "w a s d" y " " por las que estés usando en el juego; o bien, dejarlo como está y editar las del juego para cambiarlas allí. Deberían coincidir en ambos sitios las mismas teclas, tu decides. Puedes usar la Modificación para crear tus propios cargadores.
 
Abre tu MPAGD, abre el proyecto, pulsa F5 y juega para poner tu "récord", ¿quién puede superarte ahora?

"El equipo Pac-man cuenta ahora con un compositor para cualquier música y efectos de sonido necesarios en el juego, Toshio Kai se encargará de dar voz a nuestro héroe y sus amigos".

Beeper


Comentarios

Entradas populares de este blog

El laberinto