Here's a bit of fun. In this tutorial we're going to jazz up the stock 'HORIZONTAL PATROL' script that MPAGD ships with and make it possible to stun the enemy if we jump on its head....and if we do it three times in a row...we kill him, turn him into a skeleton and let him float up into the ether. Along the way we'll learn some useful tips for handling sprite TYPE switching and we'll be using READ and DATA for varying some sprite movement.
Hopefully we should end up with something like this...
So, a few things to note:
If we bounce less than three times the enemy will be stunned, recover and then continue moving in the direction they were travelling before they were stunned.
If we bounce three times on their head they will be turned into a skeleton, and then gracefully wobble their way up to the heavens
Here's the code for the enemy knight:
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
ENDIFIf you are familiar with the standard MPAGD horizontal patrol the first half of the script is pretty much the same, in essence it checks the enemy can move in a direction and isn't going to hit a wall, the edge of the screen or fall off the edge of a platform. The stock routine uses DIRECTION = LEFT and DIRECTION= RIGHT although, in reality, these are stored as numbers 0 and 1.
We are going to take advantage of this by using the number 3 (and above) to indicate the sprite has been stunned.
First we check if the player collides when they are above the enemy, by at least 14 pixels. Anything lower than this will be a failed stun and the player will be punished. As in previous tutorials I'm assuming you are using a couple of Global Variables to store the players X and Y (I use F and G).
You could make the test for a successful Stun a bit more challenging by testing the players X position (F) against the enemies X to see if they are directly (or nearly) above the enemy when they collide...but I'm keeping it simple.
Each time the player bounces on the enemies head we increment DIRECTION, so that when it hits 5 (the third bounce) we start the kill routine.
At this point I change the sprites IMAGE (to a Skeleton), its TYPE, and I also reset the FRAME to 0 and its SETTINGA to 0.
I need to do this because of an important characteristic of MPAGD when we switch a Sprites TYPE. Basically all of its parameters are switched to the new TYPE. Now, my knight sprite has 2 frames (0 and 1), whereas my Skeleton sprite has only 1. You might think that I could overcome this by adding the correct parameters into the SPRITE INITIALISATION script, but TYPE switching does not initialise a new sprite, it simply changes its TYPE. So if I was on FRAME 1 right before the Knight became a Skeleton, the Skeleton would try to display FRAME 1...which doesn't exist, and would get confused and display garbage or another sprite frame entirely.
Similarly, as both of the scripts for the knight and the skeleton use SETTINGA, I need to reset it to 0 before switching.
Right, with that out the way, lets have a look at the Skeleton script:
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
ENDIFThis is pretty straightforward. We start with a little timer so that the skeleton doesn't move for a second or so, then we have a series of potential directions that the sprite can move, we then change the DIRECTION value by reading the next value from the DATA each time we cycle through the code. BY change the DATA values or adding new pattern statements, we can add interesting movements to our sprites.
Finally, we check where the sprite is, to see if he is moving off the top of the screen before removing him.
And that's its, stunning enemies and floaty skeletons....huzzah!
