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:
Si rebotamos menos de tres veces, el enemigo quedará aturdido, se recuperará y seguirá moviéndose en la dirección en la que iba antes de ser aturdido.
Si rebotamos tres veces sobre su cabeza, se convertirá en un esqueleto y luego subirá, bamboleándose con elegancia, hasta los cielos
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
ENDIFSi 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
ENDIFEsto 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!
