Minilop Retroware

MPAGD Advanced

Creating Crusher/Lifts with MPAGD

15 November 2020

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

ENDIF

Also, 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
ENDIF

As 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!

All MPAGD Advanced