Minilop Retroware

MPAGD Avanzado

Crear aplastadores y ascensores con MPAGD

15 de noviembre de 2020

MPAGD incluye de serie un script para una plataforma móvil vertical (ascensores). Es bastante básico y no era lo que buscaba, pero con un poco de trabajo conseguí un efecto con el que quedé lo bastante satisfecho como para usarlo en mi primer juego, Cocoa and the Time Machine. También escribí para ese juego un script para aplastadores, bloques que suben y bajan y que el jugador tiene que esquivar para no sufrir un golpe aplastante. No pude evitar notar las similitudes en el código de los dos eventos, así que cuando me puse a escribir 24 Hour Parsley People los combiné, para poder usar el mismo script para un ascensor y un aplastador, ahorrando de paso unos preciosos bytes.

Primero veamos la plataforma móvil de serie. En el vídeo de abajo, el bloque amarillo es la plataforma móvil vertical estándar de MPAGD (los cian son mi versión... ya llegaremos a ellos más adelante)

La versión estándar funciona bastante bien como plataforma móvil, el jugador puede subirse y bajarse sin problema. Cuando el ascensor baja, visualmente no queda muy bien... se ve cómo el sprite del jugador rebota. Otra cosa que no me gustaba es que el jugador parece poder atravesarlo caminando, algo que nunca queda bien, y que no iba a servir para que funcionara como aplastador. Además, la versión estándar deja de subir si el jugador puede quedar atrapado arriba; de nuevo, yo quería que funcionara de forma algo distinta: para añadir peligro quiero que el jugador salga herido si se queda en el ascensor (¡al fin y al cabo es un ascensor aplastador!)

Otro efecto que quería añadir era que el ascensor suba lentamente y luego caiga más deprisa.

Aquí tienes un vídeo con una versión simplificada de mi código, que usaremos para este tutorial:

Si te fijas (mira el valor de Health), los ascensores aplastadores causarán daño si el jugador queda aplastado arriba y si un aplastador cae sobre él.

Y aquí está el código:

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

Además, vamos a necesitar poner algunos ajustes en el script Sprite Initialisation...

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

Como puedes ver, el código principal se divide en dos partes. La primera es qué hacer si el jugador colisiona con el aplastador/ascensor, ya sea encima de él, yendo de paseo, o siendo aplastado arriba o abajo; también gestiona qué hacer si el jugador choca con un lado.

La segunda parte son las cuatro acciones principales del aplastador/ascensor: está subiendo, esperando arriba, cayendo o esperando abajo.

No recuerdo por qué usé SETTINGA para, en la práctica, las direcciones, y el parámetro DIRECTION como el número de ciclos que controla el tiempo de espera hasta el que SETTINGB se incrementa cuando el aplastador/ascensor está arriba o abajo... pero si no está roto, ¡no lo voy a arreglar!

Hay mucho que pasa en este script, pero es bastante flexible y te da dos funciones nuevas en una. Por supuesto, siéntete libre de adaptarlo a las necesidades de tus propios juegos y entornos.

¡Espero que te sirva de ayuda!

Todo MPAGD Avanzado