Minilop Retroware

MPAGD Avançado

Criar esmagadores e elevadores com MPAGD

15 de novembro de 2020

O MPAGD inclui de origem um script para uma plataforma móvel vertical (elevadores). É bastante básico e não era o que eu procurava, mas com algum trabalho consegui um efeito com que fiquei satisfeito o suficiente para o usar no meu primeiro jogo, Cocoa and the Time Machine. Também escrevi para esse jogo um script para esmagadores, blocos que subiam e desciam e que o jogador precisava de esquivar para não sofrer um golpe esmagador. Não pude deixar de notar as semelhanças no código dos dois eventos, por isso, quando comecei a escrever 24 Hour Parsley People, combinei-os, para poder usar o mesmo script para um elevador e um esmagador, poupando alguns preciosos bytes pelo caminho.

Primeiro vamos ver a plataforma móvel de origem. No vídeo abaixo, o bloco amarelo é a plataforma móvel vertical padrão do MPAGD (os ciano são a minha versão... já lá vamos)

A versão padrão funciona suficientemente bem como plataforma móvel, o jogador pode saltar para cima e para fora sem problemas. Quando o elevador desce, visualmente não é ótimo... vê-se o sprite do jogador a ressaltar. Outra coisa de que não gostava era o facto de o jogador aparentemente poder atravessá-lo a andar, o que nunca fica bem e não ia servir para funcionar como esmagador. Além disso, a versão padrão deixa de subir se o jogador puder ficar preso no topo; também aqui queria que funcionasse de forma ligeiramente diferente: para acrescentar perigo, quero que o jogador se magoe se ficar no elevador (afinal é um elevador esmagador!)

Outro efeito que queria acrescentar era fazer o elevador subir devagar e depois cair mais depressa.

Aqui está um vídeo com uma versão simplificada do meu código, que vamos usar neste tutorial:

Se reparares (olha para o valor de Health), os elevadores esmagadores causam dano se o jogador for esmagado no topo e se um esmagador cair sobre ele.

E aqui está o 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

Além disso, vamos precisar de colocar algumas definições no 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 podes ver, o código principal está dividido em duas partes. A primeira é o que fazer se o jogador colidir com o esmagador/elevador, quer em cima dele, a ir à boleia, quer sendo esmagado no topo ou em baixo; também trata do que fazer se o jogador chocar com um dos lados.

A segunda parte são as quatro ações principais do esmagador/elevador: está a subir, a esperar no topo, a cair ou a esperar em baixo.

Não me lembro porque usei SETTINGA para, na prática, as direções, e o parâmetro DIRECTION como o número de ciclos que controla o tempo de espera até ao qual SETTINGB é incrementado quando o esmagador/elevador está no topo ou em baixo... mas se não está estragado, não vou arranjá-lo!

Há muita coisa a acontecer neste script, mas é bastante flexível e dá-te duas funcionalidades novas numa só. Obviamente, sente-te à vontade para o adaptares às necessidades dos teus próprios jogos e ambientes.

Espero que isto ajude!

Todo o MPAGD Avançado