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
ENDIFAlé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
ENDIFComo 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!
