Minilop Retroware

MPAGD Principiantes · Parte 26 de 29

Vamos a crear un juego con MPAGD, Parte 26: Mejorar la rutina KILL PLAYER y el cambio de TYPE

2 de noviembre de 2021

Quiero darle un poco de pulido al juego mejorando lo que pasa cuando matan a Stinky Dog.

Ahora mismo, hay tres formas de matar a Stinky Dog:

  1. Si choca con Sideways Clive

  2. Si cae sobre un bloque de pinchos DEADLY

  3. Si el aire de la sala se vuelve demasiado tóxico

Y cuando matan a Stinky Dog, simplemente reaparece en su posición original.

Vamos a hacerlo un poco más interesante: añadiremos un sonido y una animación.

La animación será una lápida que sale del suelo.

Voy a crear un sprite de 4 fotogramas para la lápida.

Primero diseñé la lápida completa; en el Sprite Editor pulsa X para añadir un sprite nuevo

Captura de pantalla del tutorial

A continuación, voy a copiar y pegar este fotograma 3 veces, lo que me dará cuatro fotogramas idénticos para este sprite. Para hacerlo, uso las teclas:

M - copiar el fotograma

I - insertar un fotograma nuevo

K - pegar el fotograma

I - insertar otro fotograma

K - pegar el fotograma en él

I - insertar el último fotograma

K - pegar el fotograma en él

Ahora tenemos un sprite de 4 fotogramas con la lápida completa en cada uno.

Para ello puedes usar las teclas D y F para recorrer los fotogramas (D hacia atrás, F hacia delante)

Para dar el efecto de que la lápida sale del suelo, tendré que desplazarla hacia arriba de 4 en 4 píxeles (4 x 4 = 16, nuestro sprite mide 16 píxeles de alto)

Asegúrate de estar viendo el Frame 000 (usa D o F para llegar a él si no)

Ahora pulsa el cursor ARRIBA cuatro veces

Captura de pantalla del tutorial

Tu sprite debería verse ahora así: lo que eran las 4 filas superiores son ahora las cuatro filas inferiores.

Ahora haz clic derecho sobre los píxeles de color de las 12 filas superiores para borrarlos. Tu Frame 0 debería verse así:

Captura de pantalla del tutorial

Cuando lo tengas, pulsa F para pasar al siguiente fotograma.

Esta vez hay que desplazarlo 8 píxeles hacia arriba: pulsa la tecla arriba 8 veces y luego borra las 8 filas superiores. El Frame 1 debería quedar así:

Captura de pantalla del tutorial

Cuando lo tengas, pulsa F para pasar al siguiente fotograma.

Esta vez pulsa el cursor ARRIBA 12 veces (o el cursor abajo 4 veces) y borra las 4 filas superiores. Debería quedar así:

Captura de pantalla del tutorial

Pulsa F para ir al último fotograma. Debería mostrar la lápida completa, que es lo que queremos, así que no hace falta editarlo.

Pulsa F otra vez y deberías volver al Frame 0. Si has creado fotogramas adicionales por accidente, puedes pulsar R para eliminarlos.

Mantén el dedo en F y deberías ver la animación en la vista previa. Será bastante rápida, pero no te preocupes, podemos controlar la velocidad en nuestro código.

Ahora que tenemos un sprite de lápida, vamos a escribir código para él. Lo pondré en SPRITE TYPE 8; en tu menú Events elige Sprite Type 8.

Este es el código:

EVENT SPRITETYPE8

IF IMAGE 7           ; is it the tombstone
   FALL              ; make it subject to gravity
   IF FRAME <> 3     ; if we are not on the last frame
      ANIMATE MEDIUM ; animate the tombstone
   ELSE
      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 
      KILL           ; kill the player
      EXIT           ; stop processing this event
   ENDIF	
ENDIF

Primero, lo he envuelto todo en una sentencia IF IMAGE 7. Lo he hecho porque es probable que use el Type 8 para otros sprites no relacionados en el futuro; así, este código solo se ejecutará para el sprite de la lápida.

Después le he aplicado gravedad para que CAIGA (FALL) hasta los bloques de abajo, ¡así no acabaremos con lápidas flotando en el aire!

A continuación compruebo si NO estamos mostrando el último sprite. IF FRAME <> 3 significa Si NO es el Frame 3.

Y si no estamos mostrando el Frame 3, quiero que el fotograma se ANIME (es decir, que recorra los fotogramas) a velocidad MEDIUM.

ANIMATE acepta los argumentos:

Después tengo un ELSE, es decir, qué debe pasar cuando hemos llegado al FRAME 3. Esto reproducirá un sonido. Ten en cuenta que, una vez más, uso RND como variable temporal para controlar el efecto de sonido.

Una vez que ha sonado, mataremos al jugador con KILL, lo que activará la rutina KILL PLAYER.

Por último, he añadido un comando EXIT, que le dice a MPAGD que deje de procesar este evento. Puede que no lo necesitemos, pero suelo ponerlo cuando es probable que más adelante haya más código en este evento que no quiero que se ejecute si el jugador ya ha muerto.

A continuación, tenemos que actualizar nuestro PLAYER EVENT para poder activar la lápida cuando maten a Stinky Dog. Abre tu evento del jugador y busca la sentencia IF DEADLY, que controla lo que pasa cuando Stinky Dog toca un bloque mortal como los pinchos de nuestro juego. Probablemente se vea así:

IF DEADLY
   KILL
ENDIF

Vamos a cambiarlo por esto:

IF DEADLY            ; am I touching something deadly?
   LET IMAGE = 7     ; if so, turn me into the tombstone sprite   
   LET FRAME = 0     ; reset me to frame 0
   LET TYPE = 8      ; make me a type 8 sprite
   EXIT              ; stop processing this event
ENDIF

Así que, cuando Stinky Dog toque un pincho mortal, cambiaremos su imagen de sprite a 7 (la lápida). También lo convertiremos en TYPE 8 para que, a partir de ahora, el código del evento TYPE 8 controle la lápida.

Ten en cuenta que también quiero asegurarme de que, la primera vez que ejecutemos el código del TYPE 8, lo hagamos desde el FRAME 0. Cuando haces un TYPE SWITCH a un sprite, todas las variables del sprite original, incluido el número de FRAME, pasan al nuevo sprite. Como no podemos estar seguros de en qué fotograma estaba Stinky Dog cuando toca un bloque mortal, queremos asegurarnos de que la lápida empiece desde su primer fotograma (FRAME 0).

Vale, vamos compilarlo y probarlo:

¡Funciona! Cuando Stinky Dog toca un bloque mortal aparece la lápida y lo matan.

Pero no ocurre cuando lo mata Sideways Clive, y tampoco ocurrirá si el medidor de pureza del aire llega a 0. Porque hasta ahora solo hemos cambiado el tipo de sprite en el código IF DEADLY.

Así que podríamos añadir el mismo código en el código de COLLISION que detecta cuándo Sideways Clive toca a Stinky Dog, y en el código que mata a Stinky Dog cuando la pureza del aire llega a 0.

Eso es mucho código repetido y, a medida que el juego se desarrolle, lo más probable es que añadamos nuevas formas de matar a Stinky Dog. Sería mejor escribir una rutina que podamos activar siempre que queramos matar al perro. El evento KILL PLAYER no es lo mejor para esto, porque en realidad queremos controlar lo que pasa JUSTO ANTES de matar al jugador en el código.

Es mejor entonces mantenerlo en el PLAYER EVENT.

Y para ello vamos a usar una de las variables especiales de sprite para activarlo.

Voy a usar SETTINGA como variable; es una variable LOCAL, es decir, es única para cada SPRITE. En el Player Event, añade el siguiente código:

IF SETTINGA = 99     ; do we want to kill Stinky Dog
   LET IMAGE = 7     ; if so, turn me into the tombstone sprite   
   LET FRAME = 0     ; reset me to frame 0
   LET TYPE = 8      ; make me a type 8 sprite
ENDIF

Así que ahora, siempre que queramos matar al perro, solo tenemos que hacer LET SETTINGA = 99

Ahora podemos actualizar el código mortal así:

IF DEADLY                ; am I touching something deadly?
   LET SETTINGA = 99     ; run the kill code
ENDIF

Y la comprobación de la pureza del aire así:

IF P <= 0             ; if air purity is 0
   LET SETTINGA = 99  ; run the kill code
ENDIF

Vale, esto está bien para lo que comprobamos en el PLAYER EVENT, pero ¿y la detección de colisión con Sideways Clive? Porque ese código está en el evento de Clive (Sprite Event 1) y ahora mismo se ve así:

IF COLLISION PLAYER        ; if Clive touches Stinky Dog
   IF DIRECTION <> 5       ; and if Clive is not stunned
      KILL                 ; Kill Stinky Dog
   ENDIF
ENDIF

Como SETTINGA es local de Stinky Dog, no podemos simplemente sustituir el comando KILL por LET SETTINGA = 99 en el código anterior, ya que eso cambiaría en realidad el valor SETTINGA de Sideways Clive a 99. Por suerte, MPAGD tiene una solución: OTHER...ENDSPRITE.

IF COLLISION PLAYER        ; if Clive touches Stinky Dog
   IF DIRECTION <> 5       ; and if Clive is not stunned
      OTHER                ; switch to Stinky Dog
      LET SETTINGA = 99    ; run the death code
      ENDSPRITE            ; switch back to Sideways Clive
   ENDIF
ENDIF

OTHER solo se puede usar dentro de una sentencia IF COLLISION. Nos permite cambiar al OTRO sprite con el que está chocando el sprite actual (en este caso Clive). Siempre debemos volver al sprite actual con el comando ENDSPRITE.

Bien, ¡probémoslo!

Nada mal: ahora sale la lápida cuando Stinky Dog toca un bloque DEADLY o a Clive, y si la pureza del aire llega a 0.

El único problema que veo es que Clive sigue caminando sobre la lápida, de modo que los gráficos se pisan y queda un poco desordenado.

Veamos cómo podemos mejorarlo.

Añadiremos código en el Type 1 (Clive):

IF COLLISION 8     ; if we touch a type 8 (tombstone)
   UNDOSPRITEMOVE  ; move clive off the tombstone
ENDIF 

Lo que debería hacer esto es que, si Clive choca con un sprite TYPE 8 (como la lápida), UNDOSPRITEMOVE deshará el movimiento que causó la colisión y, en la práctica, lo apartará de la lápida.

¡Probemos otra vez!

¡Con eso nos vale por ahora!

Todo MPAGD Principiantes