Minilop Retroware

MPAGD Principiantes · Parte 23 de 29

Vamos a crear un juego con MPAGD - Parte 23: Añadir sonidos básicos con BEEP y CRASH

30 de octubre de 2021

Como estamos trabajando en un clásico juego de ZX Spectrum, sería un descuido no incluir unos cuantos sonidos nostálgicos del altavoz del Speccy. Aunque podríamos añadir sonidos AY para máquinas de 128K, eso no es realmente algo para principiantes. Así que nos quedaremos con el altavoz y usaremos dos comandos de MPAGD que pueden hacer ruido.

BEEP

El comando BEEP espera un número que controla durante cuánto tiempo suena. Ten en cuenta que no podemos controlar directamente el tono: los BEEP de MPAGD empiezan graves y van subiendo poco a poco durante la duración del BEEP... básicamente suena como un chapoteo. Acepta valores hasta (creo que 125, a partir de ahí empieza a dar la vuelta (así que BEEP 130 suena igual que BEEP 5)

Aquí tienes un trozo de código que puedes probar. Ponlo al final de tu evento Game Initialisation:

LET A = 5                 ; store the value 5 in A
WHILE A < 255             ; do the following as long as A is less than 255
WAITKEY                   ; Wait for a key to be pressed
AT 10 10                  ; start at line 10 column 10
PRINT "BEEP "             ; display "BEEP" 
AT 10 15
DISPLAY TRIPLEDIGITS A    ; ...and the current value of A 
BEEP A                    ; make the BEEP sound for current value of A
ADD 5 TO A                ; increase A by 5 and repeat the process
ENDWHILE

guarda tu evento y compila el juego:

Como puedes oír, BEEP 5 es poco más que un golpecito, mientras que BEEP 125 es un sonido largo y de chapoteo.

¡Está claro que aquí no tenemos mucho con lo que jugar!

CRASH

El otro sonido que podemos usar es CRASH, que produce un sonido de ruido blanco. Vamos a sustituir los BEEP de nuestro código de arriba por CRASH y a ver cómo suena:

Vale, esto va a dar trabajo.

Ese BEEP 5 corto, el golpecito, podría quedar bien cuando Stinky Dog se mueve. Veamos qué pasa si lo añadimos a su código de movimiento. Abre tu evento PLAYER y busca las dos sentencias que controlan el movimiento a izquierda y derecha. Vamos a meter BEEP 5 en ellas:

   IF KEY LEFT                ; Is the left key pressed?
       LET DIRECTION = LEFT   ; if so, remember I am going LEFT
       LET IMAGE = 1          ; display the left facing image
       IF X <= LEFTEDGE       ; are we at the left edge of the screen?
           SCREENLEFT         ; if so, go to the screen to left on the map
           LET X = RIGHTEDGE ; and put me at the right edge of that screen
           EXIT               ; and stop processing this event
       ELSE                   ; if I'm not at the left edge
           IF CANGOLEFT       ; is there space to the left of me?
              SPRITELEFT      ; if so move me left
              BEEP 5          ; make a tap sound
              ANIMATE         ; and animate me
	   ELSE               ; if I can;t go left    
	      DIG LEFT        ; dig away any fodderblocks there
           ENDIF
       ENDIF
   ENDIF

   IF KEY RIGHT               ; Is the right key pressed?
      LET DIRECTION = RIGHT   ; if so, remember I am going RIGHT
      LET IMAGE = 0           ; display the right facing image
      IF X >= RIGHTEDGE       ; Am I at the right edge of the screen?
         SCREENRIGHT          ; if so go to the screen to right on the map
         LET X = LEFTEDGE     ; and put me at the left edge
         EXIT                 ; and stop processing this event
      ELSE                    ; if I'm not at the right edge
         IF CANGORIGHT        ; is there space to the right of me?
            SPRITERIGHT       ; if so, move me right
            BEEP 5            ; make a tap sound
            ANIMATE           ; and animate me
	 ELSE                 ; if I cant go right
	    DIG RIGHT         ; dig away any fodderblocks there
         ENDIF
      ENDIF
   ENDIF

Probémoslo...

Vale, funciona, pero creo que hay un par de cosas que mejorar. Primero, creo que da demasiados golpecitos, nos vendría bien reducir su número. Segundo, los golpecitos continúan cuando Stinky Dog salta a izquierda o derecha.

Ambos problemas se deben a que el comando BEEP está dentro de las sentencias IF KEY LEFT/RIGHT. Pero los dos se pueden resolver.

Primero, veamos cómo reducir el número de golpecitos. Lo conseguiremos introduciendo un temporizador de uso general. Usaremos una variable, A, y escribiremos un poco de código que asegure que la mitad del tiempo A contiene 0 y la otra mitad contiene 1. Después haremos que el BEEP dependa de que A contenga 0.

Como siempre queremos que este temporizador esté funcionando, el mejor sitio para ponerlo es el evento MAIN LOOP 1. MPAGD ejecuta este evento en cada ciclo antes de todos los eventos de nuestros sprites (después ejecuta MAIN LOOP 2.

Abre MAIN LOOP 1, puede que ya contenga algo de código (no te preocupes por él) y añade el código resaltado de abajo:

ADD 1 TO A         ; increment A
IF A = 2           ; does A contain 2?
   LET A = 0       ; if so make A contain 0
ENDIF

Vale, ahora en nuestro código del jugador solo tenemos que envolver los BEEP 5 en una condición de que A sea 0, es decir:

IF A = 0
   BEEP 5
ENDIF

Así que ahora el sonido de golpecito solo ocurrirá la mitad de las veces (un ciclo sí y otro no)

El segundo problema, que el golpecito suene cuando Stinky Dog está en el aire, también se resuelve fácilmente. Para cada sprite, MPAGD también guarda una variable especial que nos dice si el sprite está 'en el aire' o sobre suelo firme, y se llama AIRBORNE. Como cualquier variable, contiene un valor de 0 a 255. Si es 0, significa que el sprite NO está en el aire. De nuevo, tenemos que envolver nuestros BEEP 5 en una condición que compruebe que Stinky Dog está en el suelo. Y podemos hacerlo dentro de la condición IF A = 0:

IF A = 0              ; if A contains 0
   IF AIRBORNE = 0    ; and Stinky Dog is not in the air
      BEEP 5          ; make the tap sound
   ENDIF
ENDIF

Tu código de movimiento en el evento Player debería verse ahora así:

   IF KEY LEFT                  ; Is the left key pressed?
      LET DIRECTION = LEFT      ; if so, remember I am going LEFT
      LET IMAGE = 1             ; display the left facing image
      IF X <= LEFTEDGE          ; are we at the left edge of the screen?
          SCREENLEFT         ; if so, go to the screen to left on the map
          LET X = RIGHTEDGE  ; and put me at the right edge of that screen
          EXIT                  ; and stop processing this event
      ELSE                      ; if I'm not at the left edge
         IF CANGOLEFT           ; is there space to the left of me?
            SPRITELEFT          ; if so move me left
	    IF A = 0            ; if A contains 0
	       IF AIRBORNE = 0  ; and Stinky Dog is not in the air
	          BEEP 5        ; make a tap sound
	       ENDIF
	   ENDIF
	 ELSE                   ; if I can't move left
	    DIG LEFT            ; dig any fodder blocks to the left
         ENDIF
      ENDIF
   ENDIF

   IF KEY RIGHT                 ; Is the right key pressed?
      LET DIRECTION = RIGHT     ; if so, remember I am going RIGHT
      LET IMAGE = 0             ; display the right facing image
      IF X >= RIGHTEDGE         ; Am I at the right edge of the screen?
         SCREENRIGHT          ; if so go to the screen to right on the map
         LET X = LEFTEDGE       ; and put me at the left edge
         EXIT                   ; and stop processing this event
      ELSE                      ; if I'm not at the right edge
         IF CANGORIGHT          ; is there space to the right of me?
            SPRITERIGHT         ; if so, move me right
	    IF A = 0            ; if A contains 0
	       IF AIRBORNE = 0  ; and stinky dog is not in the air
		  BEEP 5        ; make a tap sound
	       ENDIF
            ENDIF
            ANIMATE             ; and animate me
	 ELSE                   ; if I can't move right
	    DIG RIGHT           ; remove any fodderblcoks on the right
         ENDIF
      ENDIF
   ENDIF

Hora de probar...

¡Con eso vale!

A continuación quiero probar algo un poco distinto: quiero un sonido especial para cuando maten a Stinky Dog

Lo que podríamos hacer es repetir algunos sonidos en sucesión, quizá usando una variable para controlar el valor del BEEP... Algo así:

LET RND = 5         ; use RND as a temporary variable staring value of 5
REPEAT 20           ; do the following 20 times
   BEEP RND         ; make sound based on current RND
   DELAY 2          ; a very brief pause
   ADD 5 TO RND     ; increase the BEEP value by 5
ENDREPEAT           ; 

¿Por qué uso RND como variable? En pocas palabras, las variables son algo precioso en MPAGD, solo tenemos unas cuantas, y si solo necesitamos usar una variable brevemente, suelo usar RND.

Normalmente el valor guardado en RND será el último número aleatorio que haya generado nuestro código si hemos usado el comando RANDOMISE.

Dicho esto, en el código de arriba podrías usar la variable que quieras, pero en mi experiencia, usa tus variables principales de MPAGD (ABC, etc.) para 'variables globales': cosas que necesitas guardar y con las que trabajar a lo largo de todo el juego.

También he puesto un DELAY muy pequeño. DELAY pausará tu juego durante un tiempo que depende del número que pongas después. 2 es tan bajo que probablemente no se note.

Creo que el sonido que genera este código podría ser bueno para cuando maten a Stinky Dog, así que vamos a meterlo en el evento KILL PLAYER...

EVENT KILLPLAYER

LET RND = 5         ; use RND as a temporary variable staring value of 5
REPEAT 20           ; do the following 20 times
   BEEP RND         ; make sound based on current RND
   DELAY 2          ; a very brief pause
   ADD 5 TO RND     ; increase the BEEP value by 5
ENDREPEAT 
SUBTRACT 1 FROM LIVES       ; reduce the number of lives by one
COLOUR 66                   ; bright red on black
AT 0 27                     ; line 0 column 27
DISPLAY DOUBLEDIGITS LIVES  ; display lives in xx format
ZEROBONUS                   ; remove any accrued fart bonus

Vamos a probarlo...

Volveremos para hacer más sonidos en otra ocasión, pero espero que este tutorial te haya dado una buena idea de lo que se puede conseguir con los sonidos básicos del altavoz del Speccy en MPAGD. También hemos aprendido a usar:

Todo MPAGD Principiantes