Minilop Retroware

MPAGD Principiantes · Parte 29 de 29

Vamos a crear un juego con MPAGD, Parte 29: Añadir un temporizador/cuenta atrás a tu juego

7 de noviembre de 2021

Supón que en tu juego quieres dar al jugador una cantidad de tiempo fija para completar cada pantalla. Y luego, quizá, darle una bonificación según el tiempo que le quede cuando complete con éxito los objetivos del nivel.

¿Cómo lo haríamos?

Primero, MPAGD funciona a 25 fotogramas por segundo, así que debería ser bastante sencillo crear un mecanismo de tiempo que cuente segundos.

Segundo, necesitaremos algunas variables para guardar (y mostrar) la cantidad actual de minutos/segundos restantes.

Tercero, puede que queramos cambiar el tiempo permitido pantalla por pantalla, o quizá usar niveles de dificultad para alterar el tiempo permitido.

MÉTODO 1 - Sencillo: la misma cantidad de tiempo en cada pantalla

Empezaremos con una versión sencilla, donde cada pantalla tiene una cantidad fija de segundos y minutos para completarla; si el temporizador llega a 0, el jugador muere.

Bien, MPAGD funciona a 25 fotogramas por segundo. Así que si tenemos una variable que se incrementa una vez por fotograma, cuando llegue a 25 habremos cronometrado un segundo.

Usaremos la variable G como nuestro tiempo general, contando 1/25 de segundo.

También necesitaremos variables que guarden el número de minutos y segundos permitidos por pantalla:

M = Minutos

S = Segundos.

Inicializaremos los valores de estas tres variables en nuestro evento RESTART SCREEN; así se reiniciarán cada vez que empecemos una pantalla, incluso después de una muerte. En tu evento restart screen añadirás:

LET G = 0         ; reset the 1/25s timer
LET M = 1         ; countdown minutes allowed
LET S = 0         ; countdown seconds allowed

A continuación, añadiremos código que haga y muestre la cuenta atrás. Para asegurarnos de que se ejecute de forma constante durante todo el juego, lo pondremos en el evento MAINLOOP 1, de modo que se ejecute al comienzo de cada fotograma:

; COUNTDOWN TIMER
;================

ADD 1 TO G               ; increment the general timer
IF G = 25                ; when it reaches 25
   LET G = 0             ; reset it
   SUBTRACT 1 FROM S     ; decrement seconds remaining
ENDIF

IF S = 0                 ; if 0 seconds
   IF M = 0              ; and 0 minutes left
      KILL               ; kill the player
      EXIT               ; exit processing this event
   ENDIF
   SUBTRACT 1 FROM M     ; decrement the minutes
   LET S = 59            ; reset the seconds
ENDIF

COLOUR 71                ; white text on black (zx spectrum)                 
AT 22 26
DISPLAY DOUBLEDIGITS M   ; display minutes remaining
CHR 58                   ; ':'
DISPLAY DOUBLEDIGITS S   ; display seconds remaining

Así que incrementamos G; cuando llega a 25 lo reiniciamos a 0 y decrementamos el número de segundos (S); cuando S llega a 0 lo reiniciamos a 59 y decrementamos el número de minutos, salvo que no queden minutos, en cuyo caso se nos ha acabado el tiempo y matamos al jugador. Así es como debería verse...

MÉTODO 2 - Avanzado: distinta cantidad de tiempo por pantalla

Si queremos alterar el tiempo disponible, solo tenemos que cambiar el código de inicialización de variables de nuestro evento RESTART SCREEN para usar una tabla DATA y hacer READ de los valores de Minutos (M) y Segundos (S)

Podemos usar esto para la inicialización de variables en RESTART SCREEN

LET G = 0           ; reset the 1/25s timer
RESTORE             ; restore the data table so we read from the start
READ M              ; read the 1st data and put it in M
READ S              ; read 2nd value put it in S
IF SCREEN >= 1      ; if it is screen 1 or above
   REPEAT SCREEN    ; then repeat SCREEN-many times
   READ M           ; read the next value for M
   READ S           ; and the next value for S
   ENDREPEAT        ; so we've found the right M & S values for the Screen
ENDIF

Luego añadiremos esto como nuestra tabla DATA; los valores alternan entre minutos y segundos, así que el tiempo permitido en la SCREEN 0 es 0 minutos y 30 segundos (los 2 primeros valores), para la SCREEN 1 es 1 minuto y 0 segundos (valores 3 y 4), para la Screen 2 es 1 minuto y 15 segundos (valores 5 y 6), y así sucesivamente.

DATA 0 30 1 0 1 15 2 0 1 45 1 30 1 0 1 30 

Añadir una bonificación por completar la pantalla

Todo lo que hemos hecho hasta ahora sirve para matar al jugador si se le acaba el tiempo, pero ¿y si completa los objetivos de la pantalla? Podríamos añadir una bonificación según el tiempo restante. Dependiendo de qué active la finalización de la pantalla (en Stinky Dog es recoger todos los huesos), tendrás que añadir tu rutina de bonificación en el evento adecuado. Podría ser algo así:

   IF M > 0             ; if there are minutes left
      REPEAT M          ; repeat for each minute remaining
	 REPEAT 60      ; repeat 60 times (60 sec)
	    BONUS 10    ; increase bonus by 10
	 ENDREPEAT
      ENDREPEAT
   ENDIF
   IF S > 0             ; if there are seconds left
      REPEAT S          ; repeat for each second
	 BONUS 10       ; increase the bonus by 10
      ENDREPEAT
   ENDIF
   ADDBONUS             ; add the bonus to the score
   ZEROBONUS            ; reset bonus to zero

Aplicarlo a nuestro juego Stinky Dog

En nuestro juego Stinky Dog, sin embargo, hay un par de cambios que quiero hacer.

Primero, ya tenemos una tabla DATA en RESTART SCREEN 0, que guarda el número de huesos que hay que recoger por pantalla. No hay problema, a MPAGD no le importa qué datos guarda en la tabla DATA, así que solo tenemos que incluir los valores de huesos y hacer READ tres veces por ciclo para obtener el número correcto de huesos, minutos y segundos.

LET G = 0           ; reset the 1/25s timer
RESTORE             ; restore the data table so we read from the start
READ M              ; read the 1st data and put it in M
READ S              ; read 2nd value put it in S
READ B              ; read third value and put it in B for Bones
IF SCREEN >= 1      ; if it is screen 1 or above
   REPEAT SCREEN    ; then repeat SCREEN-many times
   READ M           ; read the next value for M
   READ S           ; and the next value for S
   READ B           ; and the next values for B
   ENDREPEAT        ; we've found the right M, S & B values for the Screen
ENDIF

Y la tabla DATA al final de RESTART SCREEN:

DATA 0 30 6 1 0 7 1 15 3 2 0 4 1 45 6 1 
DATA 30 4 1 0 8 1 30 6 

A continuación, como ya hemos creado una rutina de muerte reutilizable a la que llamamos poniendo el valor SETTINGA de Stinky Dog en 99, voy a mover el código del temporizador de cuenta atrás de MAINLOOP 1 al evento del jugador, quitar el comando KILL y cambiarlo por LET SETTINGA = 99

NOTA: Coloca el código DESPUÉS de tu rutina IF SETTINGA = 99 ....ENDIF

; COUNTDOWN TIMER
;================

ADD 1 TO G               ; increment the general timer
IF G = 25                ; when it reaches 25
   LET G = 0             ; reset it
   SUBTRACT 1 FROM S     ; decrement seconds remaining
ENDIF

IF S = 0                 ; if 0 seconds
   IF M = 0              ; and 0 minutes left
      LET SETTINGA = 99  ; kill the player
      EXIT               ; exit processing this event
   ENDIF
   SUBTRACT 1 FROM M     ; decrement the minutes
   LET S = 59            ; reset the seconds
ENDIF

COLOUR 71                ; white text on black (zx spectrum)                 
AT 22 26
DISPLAY DOUBLEDIGITS M   ; display minutes remaining
CHR 58                   ; ':'
DISPLAY DOUBLEDIGITS S   ; display seconds remaining


Aquí lo tienes en acción cuando se nos acaba el tiempo

Para añadir una bonificación de tiempo nueva al completar la pantalla tendremos que actualizar nuestro evento COLLECT BLOCK:

EVENT COLLECTBLOCK

SCORE 100                  	; score 100 points when we collect a Bone
AT 0 6 
COLOUR 71
SHOWSCORE			; display the score

SUBTRACT 1 FROM B	; decrement the number of bones left on screen
IF B = 0                ; have all Bones been collected?
   CLS                  ; clear the screen
   AT 4 6
   MESSAGE 1            ; "well done"
   CHR 32
   MESSAGE 0            ; "stinky dog"
   CHR 33
   DELAY 25             ; wait another second
   COLOUR 65            ; bright blue on balck
   AT 7 7
   MESSAGE  2           ; "score"
   CHR 32               ; <space>
   DELAY 25             ; wait another second
   SHOWSCORE
   DELAY 25             ; wait another second
   AT 9 2
   COLOUR 70            ;  bright yellow on black
   MESSAGE 3            ; "fart"
   CHR 32               ; <space>
   MESSAGE 4            ; "bonus"
   CHR 32               ; <space>
   DELAY 25             ; wait another second
   SHOWBONUS            ; display the bonus
   ADDBONUS             ; add the bonus to the score
   ZEROBONUS            ; reset the bonus to 0 now we've added it
   DELAY 25             ; wait another second
   COLOUR 67            ; bright magenta on black
   AT 11 2
   MESSAGE 7            ; "time"
   CHR 32               ; <space>
   MESSAGE 4            ; "bonus"
   CHR 32               ; <space>
   DELAY 25             ; wait another second
   IF M > 0             ; if there are minutes left
      REPEAT M          ; repeat for each minute remaining
	 REPEAT 60      ; repeat 60 times (60 sec)
	    BONUS 10       ; increase bonus by 10
	 ENDREPEAT
      ENDREPEAT
   ENDIF
   IF S > 0             ; if there are seconds left
      REPEAT S          ; repeat for each second
	 BONUS 10       ; increase the bonus by 10
      ENDREPEAT
   ENDIF
   SHOWBONUS
   ADDBONUS             ; add the bonus to the score
   ZEROBONUS            ; reset bonus to zero  
   AT 13 5                
   COLOUR 71
   MESSAGE 8            ; "total"
   CHR 32
   CHR 61
   CHR 32 
   SHOWSCORE            ; display the score
   DELAY 25             ; wait 1 second

   AT 17 8              ; at line 15 column 8
   COLOUR 215
   MESSAGE 5            ; "press key to start"
   WAITKEY              ; wait for a key press
   NEXTLEVEL            ; if so move to the next screen
ENDIF

Fíjate en que he añadido dos mensajes nuevos a los TEXT MESSAGES:

DEFINEMESSAGES
"STINKY DOG"          ;0
"WELL DONE"           ;1
"SCORE"               ;2
"FART"                ;3
"BONUS"               ;4
"PRESS KEY TO START"  ;5
"LIVES"               ;6
"TIME"                ;7 
"TOTAL"               ;8

¡Aquí está todo funcionando de maravilla!

Todo MPAGD Principiantes