Minilop Retroware

MPAGD Avanzado

Vamos a aturdir a un enemigo saltándole en la cabeza... ¡y a matarlo a la tercera!

19 de noviembre de 2020

Aquí tienes algo divertido. En este tutorial vamos a darle más gracia al script estándar 'HORIZONTAL PATROL' que viene con MPAGD y a hacer posible aturdir al enemigo si saltamos sobre su cabeza....y si lo hacemos tres veces seguidas...lo matamos, lo convertimos en un esqueleto y lo dejamos flotar hacia el éter. De paso aprenderemos algunos trucos útiles para gestionar el cambio de TYPE de los sprites y usaremos READ y DATA para variar algún movimiento de sprite.

Con suerte acabaremos con algo así...

Así que, algunas cosas a tener en cuenta:

Este es el código del caballero enemigo:

ANIMATE

IF DIRECTION = LEFT                        ; set the direction to left
   SPRITELEFT                              ; move left
   IF CANGOLEFT                            ; can we go left?   
      SUBTRACT 16 FROM X                   ; if so look 16px to the left
      IF CANGODOWN                         ; if we were there would we be able to go down?
         LET DIRECTION = RIGHT             ; if so change the direction to right
      ELSE                                 ; if we wouldnt be able to go down
         IF X <= LEFTEDGE                  ; check if we are at the left edge
            LET DIRECTION = RIGHT          ; if we are, then change the direction to right
         ENDIF
      ENDIF
      ADD 16 TO X                          ; reset x to its original value

   ELSE                                    ; if we cant go left
      LET DIRECTION = RIGHT                ; go right
   ENDIF
ENDIF
   

IF DIRECTION = RIGHT                       ; set direction to right
   IF CANGORIGHT                           ; can we go right?
      SPRITERIGHT                          ; yes...go right then
      ADD 16 TO X                          ; look 16px to the right
      IF CANGODOWN                         ; if we were there, would we be able to go down?
         LET DIRECTION = LEFT              ; if so, change direction to left
      ELSE                                 ; if not
         IF X >= RIGHTEDGE                 ; check if we would be at the right edge
            LET DIRECTION = LEFT           ; if we are, change direction to left
         ENDIF
      ENDIF
      SUBTRACT 16 FROM X                   ; reset x to its original value
   ELSE
      LET DIRECTION = LEFT                 ; if we cant go right, go left
   ENDIF
ENDIF
     


IF COLLISION PLAYER                        ; have we collided with the player?
   IF G <= Y 				               ; is the player above us?
      SUBTRACT G FROM Y                    ; if so - by how much?
      IF Y >= 14                           ; more than 14 pixels?
	     IF DIRECTION < 3                  ; is our direction less than 3? (not stunned)
            LET SETTINGB = DIRECTION       ; remember what direction I was going in SETTINGB
            LET DIRECTION = 3              ; if so, make it 3 (anything 3 or above is stunned)
         ELSE                              ; if it was already above 3
            ADD 1 TO DIRECTION             ; add 1 to direction
         ENDIF                  
         OTHER                             ; switch to the player sprite
         STOPFALL                          ; stop the player on my head
         BEEP 80                           ; make a sound
         JUMP 6                            ; make the player jump
         ENDSPRITE                         ; switch back to tme
      ELSE                                 ; if the player is less than 14px above me when he hit me, the stun has failed
         OTHER                             ; switch to the player
         JUMP 2                            ; make the player do a little jump
         ENDSPRITE                         ; switch back to me
         SUBTRACT 1 FROM E                 ; inflict damage on the player
         BEEP 25                           ; make a damage sound
         ENDIF                             
      ENDIF
      ADD G TO Y                           ; reset the sprites y position
   ENDIF
ENDIF  


IF DIRECTION >= 3                          ; if I am stunned
   ADD 1 TO SETTINGA					   ; increment the stun timer							
   IF SETTINGA = 60                        ; is the stun time complete?
      LET DIRECTION = SETTINGB             ; if so start me moving in the direction I was going when I got stunned
      LET SETTINGA = 0                     ; reset the stun timer
   ENDIF  
   IF DIRECTION = 5                        ; have I been bounced on 3 times?
      LET IMAGE = 23                       ; if so, change me to my skeleton image
      LET TYPE = 8                         ; change my type to 8
      LET FRAME = 0                        ; change my frame to 0
	  LET SETTINGA = 0                     ; reset my SETTINGA to 0
   ENDIF
ENDIF

Si conoces la patrulla horizontal estándar de MPAGD, la primera mitad del script es prácticamente igual: en esencia comprueba que el enemigo puede moverse en una dirección y que no va a chocar con una pared, con el borde de la pantalla ni a caerse por el borde de una plataforma. La rutina estándar usa DIRECTION = LEFT y DIRECTION= RIGHT aunque, en realidad, se almacenan como los números 0 y 1.

Vamos a aprovechar esto usando el número 3 (y superiores) para indicar que el sprite ha sido aturdido.

Primero comprobamos si el jugador colisiona estando por encima del enemigo, al menos 14 píxeles. Cualquier cosa más baja será un aturdimiento fallido y el jugador será castigado. Como en tutoriales anteriores, supongo que estás usando un par de variables globales para guardar la X y la Y del jugador (yo uso F y G).

Podrías hacer la comprobación de un aturdimiento logrado algo más difícil comparando la posición X del jugador (F) con la X del enemigo, para ver si está justo (o casi) encima del enemigo cuando colisionan...pero lo voy a dejar simple.

Cada vez que el jugador rebota sobre la cabeza del enemigo incrementamos DIRECTION, de modo que cuando llega a 5 (el tercer rebote) iniciamos la rutina de muerte.

En este punto cambio la IMAGE del sprite (a un esqueleto), su TYPE, y también restablezco el FRAME a 0 y su SETTINGA a 0.

Necesito hacerlo por una característica importante de MPAGD cuando cambiamos el TYPE de un sprite. Básicamente, todos sus parámetros pasan al nuevo TYPE. Mi sprite de caballero tiene 2 frames (0 y 1), mientras que mi sprite de esqueleto solo tiene 1. Podrías pensar que lo solucionaría añadiendo los parámetros correctos en el script de SPRITE INITIALISATION, pero el cambio de TYPE no inicializa un sprite nuevo, solo cambia su TYPE. Así que si estaba en el FRAME 1 justo antes de que el caballero se convirtiera en esqueleto, el esqueleto intentaría mostrar el FRAME 1...que no existe, se confundiría y mostraría basura u otro frame de sprite completamente distinto.

De igual modo, como tanto el script del caballero como el del esqueleto usan SETTINGA, necesito restablecerlo a 0 antes del cambio.

Bien, con eso aclarado, echemos un vistazo al script del esqueleto:

IF IMAGE 23                   ; am I a skeleton?                 
   SPRITEINK 7                ; cool! make me white
   ADD 1 TO SETTINGA          ; increment the timer by 1
   IF SETTINGA >= 30          ; have we reached 30 yet?
      READ DIRECTION          ; get the next value in the DATA and set it in my DIRECTION
   ENDIF
                              ; check my DIRECTION value
   IF DIRECTION = 1           ; if it's 1
      SPRITERIGHT             ; move me right and up
	  SPRITEUP
   ENDIF
  
   IF DIRECTION = 2           ; if it's 2
      SPRITEUP                ; move me up
   ENDIF
  
   IF DIRECTION = 3           ; if it's 3 
      SPRITELEFT              ; move me left and up
	  SPRITEUP
   ENDIF
  
   ADD 8 TO Y                 ; check 8 pixels from the top of me
   IF Y <= TOPEDGE            ; is it at the top of the screen
      REMOVE                  ; if so, remove me
   ENDIF
   SUBTRACT 8 FROM Y          ; reset my Y value
  
   DATA 1 1 2 2 2 2 3 3 3 3 3 2 2 2 1 1
ENDIF

Esto es bastante sencillo. Empezamos con un pequeño temporizador para que el esqueleto no se mueva durante un segundo más o menos, luego tenemos una serie de posibles direcciones en las que puede moverse el sprite, y después cambiamos el valor de DIRECTION leyendo el siguiente valor de DATA cada vez que recorremos el código. Cambiando los valores de DATA o añadiendo nuevas instrucciones de patrón, podemos darles movimientos interesantes a nuestros sprites.

Por último, comprobamos dónde está el sprite, para ver si se sale por la parte superior de la pantalla antes de eliminarlo.

Y eso es todo: enemigos aturdidos y esqueletos flotantes....¡hurra!

Todo MPAGD Avanzado