Aqui está algo divertido. Neste tutorial vamos dar mais graça ao script padrão 'HORIZONTAL PATROL' que vem com o MPAGD e tornar possível atordoar o inimigo se saltarmos para a cabeça dele....e se o fizermos três vezes seguidas...matamo-lo, transformamo-lo num esqueleto e deixamo-lo flutuar até ao éter. Pelo caminho vamos aprender algumas dicas úteis para lidar com a troca de TYPE dos sprites e vamos usar READ e DATA para variar algum movimento de sprites.
Com sorte, vamos acabar com algo assim...
Então, algumas coisas a ter em conta:
Se saltarmos menos de três vezes, o inimigo fica atordoado, recupera e continua a mover-se na direcção em que seguia antes de ser atordoado.
Se saltarmos três vezes para a cabeça dele, transforma-se num esqueleto e depois sobe, a bambolear-se com elegância, até aos céus
Este é o código do cavaleiro inimigo:
ANIMATE
IF DIRECTION = LEFT ; set the direction to left
SPRITELEFT ; move left
IF CANGOLEFT ; can we go left?
SUBTRACT 16 FROM X ; if so look 16px to the left
IF CANGODOWN ; if we were there would we be able to go down?
LET DIRECTION = RIGHT ; if so change the direction to right
ELSE ; if we wouldnt be able to go down
IF X <= LEFTEDGE ; check if we are at the left edge
LET DIRECTION = RIGHT ; if we are, then change the direction to right
ENDIF
ENDIF
ADD 16 TO X ; reset x to its original value
ELSE ; if we cant go left
LET DIRECTION = RIGHT ; go right
ENDIF
ENDIF
IF DIRECTION = RIGHT ; set direction to right
IF CANGORIGHT ; can we go right?
SPRITERIGHT ; yes...go right then
ADD 16 TO X ; look 16px to the right
IF CANGODOWN ; if we were there, would we be able to go down?
LET DIRECTION = LEFT ; if so, change direction to left
ELSE ; if not
IF X >= RIGHTEDGE ; check if we would be at the right edge
LET DIRECTION = LEFT ; if we are, change direction to left
ENDIF
ENDIF
SUBTRACT 16 FROM X ; reset x to its original value
ELSE
LET DIRECTION = LEFT ; if we cant go right, go left
ENDIF
ENDIF
IF COLLISION PLAYER ; have we collided with the player?
IF G <= Y ; is the player above us?
SUBTRACT G FROM Y ; if so - by how much?
IF Y >= 14 ; more than 14 pixels?
IF DIRECTION < 3 ; is our direction less than 3? (not stunned)
LET SETTINGB = DIRECTION ; remember what direction I was going in SETTINGB
LET DIRECTION = 3 ; if so, make it 3 (anything 3 or above is stunned)
ELSE ; if it was already above 3
ADD 1 TO DIRECTION ; add 1 to direction
ENDIF
OTHER ; switch to the player sprite
STOPFALL ; stop the player on my head
BEEP 80 ; make a sound
JUMP 6 ; make the player jump
ENDSPRITE ; switch back to tme
ELSE ; if the player is less than 14px above me when he hit me, the stun has failed
OTHER ; switch to the player
JUMP 2 ; make the player do a little jump
ENDSPRITE ; switch back to me
SUBTRACT 1 FROM E ; inflict damage on the player
BEEP 25 ; make a damage sound
ENDIF
ENDIF
ADD G TO Y ; reset the sprites y position
ENDIF
ENDIF
IF DIRECTION >= 3 ; if I am stunned
ADD 1 TO SETTINGA ; increment the stun timer
IF SETTINGA = 60 ; is the stun time complete?
LET DIRECTION = SETTINGB ; if so start me moving in the direction I was going when I got stunned
LET SETTINGA = 0 ; reset the stun timer
ENDIF
IF DIRECTION = 5 ; have I been bounced on 3 times?
LET IMAGE = 23 ; if so, change me to my skeleton image
LET TYPE = 8 ; change my type to 8
LET FRAME = 0 ; change my frame to 0
LET SETTINGA = 0 ; reset my SETTINGA to 0
ENDIF
ENDIFSe estás familiarizado com a patrulha horizontal padrão do MPAGD, a primeira metade do script é praticamente igual: em essência, verifica se o inimigo se pode mover numa direcção e se não vai bater numa parede, no limite do ecrã ou cair do bordo de uma plataforma. A rotina padrão usa DIRECTION = LEFT e DIRECTION= RIGHT embora, na realidade, sejam guardados como os números 0 e 1.
Vamos aproveitar isto usando o número 3 (e superiores) para indicar que o sprite foi atordoado.
Primeiro verificamos se o jogador colide estando acima do inimigo, em pelo menos 14 pixels. Qualquer coisa mais baixa será um atordoamento falhado e o jogador será castigado. Tal como em tutoriais anteriores, estou a assumir que estás a usar algumas variáveis globais para guardar o X e o Y do jogador (eu uso F e G).
Podias tornar o teste de um atordoamento bem-sucedido um pouco mais desafiante testando a posição X do jogador (F) contra o X do inimigo, para ver se está mesmo (ou quase) acima do inimigo quando colidem...mas vou manter as coisas simples.
Cada vez que o jogador salta para a cabeça do inimigo incrementamos DIRECTION, de modo que quando chega a 5 (o terceiro salto) iniciamos a rotina de morte.
Neste ponto mudo a IMAGE do sprite (para um esqueleto), o seu TYPE, e também reponho o FRAME a 0 e o seu SETTINGA a 0.
Preciso de fazer isto por causa de uma característica importante do MPAGD quando mudamos o TYPE de um sprite. Basicamente, todos os seus parâmetros passam para o novo TYPE. O meu sprite de cavaleiro tem 2 frames (0 e 1), ao passo que o meu sprite de esqueleto só tem 1. Podias pensar que eu resolvia isto adicionando os parâmetros correctos ao script de SPRITE INITIALISATION, mas a troca de TYPE não inicializa um sprite novo, apenas muda o seu TYPE. Por isso, se eu estivesse no FRAME 1 mesmo antes de o cavaleiro se tornar esqueleto, o esqueleto tentaria mostrar o FRAME 1...que não existe, ficaria confuso e mostraria lixo ou outro frame de sprite completamente diferente.
Do mesmo modo, como tanto o script do cavaleiro como o do esqueleto usam SETTINGA, preciso de o repor a 0 antes da troca.
Muito bem, com isso esclarecido, vamos dar uma vista de olhos ao script do esqueleto:
IF IMAGE 23 ; am I a skeleton?
SPRITEINK 7 ; cool! make me white
ADD 1 TO SETTINGA ; increment the timer by 1
IF SETTINGA >= 30 ; have we reached 30 yet?
READ DIRECTION ; get the next value in the DATA and set it in my DIRECTION
ENDIF
; check my DIRECTION value
IF DIRECTION = 1 ; if it's 1
SPRITERIGHT ; move me right and up
SPRITEUP
ENDIF
IF DIRECTION = 2 ; if it's 2
SPRITEUP ; move me up
ENDIF
IF DIRECTION = 3 ; if it's 3
SPRITELEFT ; move me left and up
SPRITEUP
ENDIF
ADD 8 TO Y ; check 8 pixels from the top of me
IF Y <= TOPEDGE ; is it at the top of the screen
REMOVE ; if so, remove me
ENDIF
SUBTRACT 8 FROM Y ; reset my Y value
DATA 1 1 2 2 2 2 3 3 3 3 3 2 2 2 1 1
ENDIFIsto é bastante simples. Começamos com um pequeno temporizador para que o esqueleto não se mova durante um segundo ou assim, depois temos uma série de direcções possíveis em que o sprite se pode mover, e a seguir mudamos o valor de DIRECTION lendo o valor seguinte de DATA de cada vez que percorremos o código. Ao mudar os valores de DATA ou adicionar novas instruções de padrão, podemos dar movimentos interessantes aos nossos sprites.
Por fim, verificamos onde está o sprite, para ver se está a sair pela parte de cima do ecrã antes de o removermos.
E é isto: inimigos atordoados e esqueletos flutuantes....viva!
