Out of the box, MPAGD includes a script for a vertical moving platform (Lifts/Elevators). It's fairly basic and wasn't what I was looking for, but with a bit of work I managed to get an effect I was happy enough to use in my first game, Cocoa and the Time Machine. I also wrote a script for that game for Crushers, blocks that would rise and fall that the player would need to dodge else suffer a crushing blow. I couldn't help notice the similarities in the code for the two events, so when I set about writing 24 Hour Parsley People I combined the two, so I could use the same script for a Lift and a Crusher, saving a few precious bytes in the process.
First let's take a look at the stock moving platform. In the video below the Yellow block is the standard MPAGD vertical moving platform (the cyan ones are my version...we'll come on to those later)
The standard version works well enough as a moving platform, the player can jump on and off it ok. When the Lift is going down it's not visually great...you can see the player sprite bouncing. Another thing that I wasn't keen on was the fact that the player can seemingly walk right through it, which never looks good - and wasn't going to be suitable for working as a Crusher. Also, the standard version will stop rising if the player is potentially going to get trapped at the top - again I wanted it to work slightly differently - for added danger I want the player to get hurt if he stays on the Lift (it's a Crusher Lift after all!)
Another effect I was keen to add was having the lift go upward slowly and then fall more quickly.
Here's a video running a simplified version of my code that we'll use for this tutorial:
If you notice (if you look at the Health value) the Crusher Lifts will inflict damage if the player gets crushed at the top and if a crusher falls on top of them.
And here's the code:
IF IMAGE 9
SPRITEINK 13
IF COLLISION 0 ; if cocoa collides with the lift
LET P = Y ; Store the lift Y value in P
LET K = X ; STORE LIFT X VALUE IN K
OTHER ; switch to Cocoa
IF P > Y ; is crusher beneath cocoa?
SUBTRACT Y FROM P ; If so, by how many pixels?
IF P >= 6 ; more than 6?
SUBTRACT 8 FROM Y ; If so, lets look at what kind of block is above the player
GETBLOCK X Y
ADD 8 TO Y
IF BLOCK = WALLBLOCK ; is it a wall bock?
SPRITEDOWN ; if so, make the player fall off
FALL
ENDIF
IF CANGOUP ; Can the player go up?
ADD Y TO P ; lets reset the players Y value back to its original
LET Y = P
SUBTRACT 16 FROM Y ; and subtract 16 from it sp the player is now standing on the crusher/platform
STOPFALL ; and keep the player standing there
ELSE ; player cant go up any more?
SPRITEDOWN ; knock them off!
FALL
ENDIF
ELSE ; player must be stuck at the top!
SUBTRACT 10 FROM L ; that must hurt! inflict damage now!
ENDIF
ELSE ; players is BELOW THE CRUSHER
IF K < X ; is the player to the right?
IF CANGORIGHT ; if they can go right
ADD 2 TO X ; prevent the player passing through the crusher from the right
ENDIF
ELSE
IF CANGOLEFT ; player is to the left of the crusher
SUBTRACT 2 FROM X ; prevent the player passing through the crusher from the left
ENDIF
ENDIF
FALL
ENDIF
ENDSPRITE ; switch back to the Crusher
IF SETTINGA = 0
IF Y < G
SUBTRACT 10 FROM L
ENDIF
ENDIF
ENDIF
IF SETTINGA = 0 ; CRUSHER - GO DOWN
REPEAT 4 ; We'll use a repeat so the crusher goes downward quickly
IF CANGODOWN ; can it still go down?
SPRITEDOWN
ELSE ; if not
BEEP 20
LET SETTINGA = 2 ; lets make the crusher stay at the bottom
LET SETTINGB = 0 ; we use SETTINGB as a timer so lets reset it
ENDIF
ENDREPEAT
ENDIF
IF SETTINGA = 1 ; CRUSHER - GO UP
IF CANGOUP ; can the crusher go up?
IF Y >= 16 ; and is it at least 16px from the top of the Screen?
SPRITEUP ; go up!
ELSE ; if not
LET SETTINGA = 3 ; let's make the crusher wait at the top
LET SETTINGB = 0 ; SETTINGB is the timer, so reset it
ENDIF
ELSE ; if it cant go up any more
LET SETTINGA = 3 ; let's make it wait
LET SETTINGB = 0 ; and reset the timer
ENDIF
ENDIF
IF SETTINGA = 2 ; CRUSHER - WAIT AT BOTTOM
IF SETTINGB = DIRECTION ; Has the timer finished?
LET SETTINGA = 1 ; if so, tell the crusher to go up
LET SETTINGB = 0 ; and reset the timer
ELSE
ADD 1 TO SETTINGB ; timer hasnt finished so increment it 1
ENDIF
ENDIF
IF SETTINGA = 3 ; CRUSHER - WAIT AT TOP
IF SETTINGB = DIRECTION ; Has the timer finished?
LET SETTINGA = 0 ; if so, tell the crusher to go down
LET SETTINGB = 0 ; and reset the timer
ELSE
ADD 1 TO SETTINGB ; timer hasnt finished so increment it 1
ENDIF
ENDIF
ENDIFAlso, we're going to need to put a few settings into the Sprite Initialisation script...
IF TYPE {WHATEVER THE NUMBER OF YOUR SPRITE EVENT IS}
LET SETTINGA = 0 ; the initial direction of the crusher/lift
LET SETTINGB = 0 ; the counter for waiting at the top/bottom
LET DIRECTION = 16 ; the number of cycles to wait
ENDIFAs you can see the main code is split into two parts, the first is what to do if the player collides with Crusher/Lift - either on top of it and hitching a ride, or getting crushed either at the top or the bottom, it also handles what to do if the player walks into the side of it.
The second part are the four main actions of the Crusher Lift, it's either going up, waiting at the top, falling, or waiting at the bottom.
I can't remember why I used SETTINGA for, effectively, the directions, and the the DIRECTION parameter as the number of cycles which controls the waiting time that SETTINGB increments to when the Crusher/Lift is at the top/bottom!...but if its not broke I'm not going to fix it!
There's a lot going on in this script but it's quite flexible and can give you two new features in one, obviously feel free to adapt it to the needs of your own games and environments.
Hope this helps!
