Minilop Retroware

MPAGD Iniciantes · Parte 20 de 29

Vamos criar um jogo com o MPAGD, Parte 20: SCOREs, LIVES e mostrar coisas no ecrã.

30 de outubro de 2021

O nosso jogo está a começar a ganhar forma; esta é provavelmente uma boa altura para arrumar a confusão que é atualmente a barra de pontuação no topo do ecrã. Antes disso, vamos ver como o MPAGD guarda a pontuação do jogador, como lhe podemos adicionar pontos e como a mostramos no ecrã.

Primeiro, a pontuação não é uma variável normal de 8 bits. Como te lembras, as variáveis de 8 bits podem guardar um número de 0 a 255. A pontuação num jogo MPAGD pode guardar um valor de 0 a 999,999, após o que volta a 0. Não precisas de perceber como é que o faz, só que o faz!

Lembra-te que na Parte 11 adicionámos pontos sempre que o Stinky Dog recolhia um osso. Fizemos isso adicionando o comando

SCORE 100

no evento COLLECTBLOCK. O comando SCORE aceita um número de 16 bits, ou seja, qualquer número de 0 a 65,535 (2 elevado a 16). O número que colocares depois do comando SCORE é somado à pontuação atual do jogador.

Nota que SCORE não é uma variável, por isso não podes escrever código que a consulte, como IF SCORE >50000 ADD 1 TO LIVES.

Também atualizámos a pontuação no ecrã incluindo o comando:

AT 0 6
SHOWSCORE

O comando AT é uma forma abreviada de posicionar o cursor no ecrã, por isso o código acima é equivalente a:

LET LINE = 0
LET COLUMN = 6
SHOWSCORE

Mas e se também quiséssemos ter a palavra 'SCORE:' antes da pontuação, para que apareça: SCORE: 000000... isso poderia ficar mais arrumado.

Vamos abrir o nosso script de GAME INITIALISATION:

EVENT GAMEINIT


LET LIVES = 3
AT 0 27
DISPLAY LIVES

AT 0 6
SHOWSCORE

...e vamos arrumá-lo um pouco:

EVENT GAMEINIT

AT 0 0 
PRINT "SCORE:"
SHOWSCORE


LET LIVES = 3
AT 0 21
PRINT "LIVES:"
DISPLAY LIVES

Agora a nossa barra de pontuação está um pouco mais arrumada:

Captura de ecrã do tutorial

Vemos que AT 0 0 posiciona o cursor na célula de carácter do canto superior esquerdo do ecrã; depois fazemos PRINT da palavra 'SCORE:' e mostramos a pontuação real ao lado (nota que o cursor passa automaticamente para a coluna seguinte disponível, e é por isso que no nosso evento de inicialização do jogo podemos poupar alguns bytes removendo o AT 0 6 antes de SHOWSCORE... já que, depois de imprimir 'SCORE:', o cursor já lá está!).

Depois deslocamos o cursor para 0 21 para mostrar as vidas restantes.

Outro bónus relacionado com a pontuação no MPAGD é... o BONUS. Funciona de forma semelhante ao SCORE, no sentido em que podes adicionar ao bónus do jogador com um comando como:

BONUS 50

Que acionas quando o jogador faz algo. Vamos dar ao Stinky Dog um BONUS se um dos seus peidos nocivos atordoar o Sideways Clive...

Abre o teu evento SPRITETYPE 1 e encontra a parte que trata da colisão do peido com o Sideways Clive...

IF COLLISION 2             ; if Clive touches a Type 2 sprite (the fart)
   IF DIRECTION = LEFT     ; if Clive is going left
      LET SETTINGB = 0     ; remember the direction he was going, 0 = Left
   ELSE                    ; if he wasn't going left
      LET SETTINGB = 1     ; he was going RIGHT, 1 = RIGHT
   ENDIF
   LET DIRECTION = 5       ; set the direction to STUNNED
   LET SETTINGA = 0        ; start the stunned timer
   OTHER                   ; switch to the Fart 
   REMOVE                  ; remove the fart 
   ENDSPRITE               ; switch back to this event
   LET F = 0               ; reset the Fart in play to no fart in play
   BONUS 50                ; add 50 to the bonus
ENDIF

Agora, quando um peido atingir o Clive, vamos aumentar o bónus.

Nota que o BONUS não é adicionado automaticamente à pontuação: vai-se acumulando enquanto jogamos, e vamos adicioná-lo mais tarde, quando o Stinky Dog completar um nível do jogo.

Tal como o SCORE, só podes incrementar o BONUS com números até 65535 e o máximo é 999999.

Neste momento, no nosso jogo, um nível é completado quando o Stinky Dog recolhe todos os ossos do ecrã; verificamos se foram todos recolhidos no nosso evento COLLECTBLOCK, que atualmente tem este aspeto:

EVENT COLLECTBLOCK

SCORE 100                  	; score 100 points when we collect a Bone
AT 0 6 
SHOWSCORE			; display the score

SUBTRACT 1 FROM B	; decrement the number of bones left on screen
IF B = 0                ; have all Bones been collected?
   NEXTLEVEL            ; if so move to the next screen
ENDIF

Vamos torná-lo um pouco mais interessante: vamos limpar o ecrã, mostrar o bónus, adicioná-lo à pontuação e depois iniciar o nível seguinte.

Quando se trata de limpar o ecrã, temos dois comandos à escolha:

CLS: limpa o ecrã inteiro

CLW: limpa apenas a janela de jogo e não a barra de pontuação que temos no topo (ou onde tiveres posicionado a tua!)

Vamos limpar o ecrã, mostrar a pontuação, o bónus, adicionar o bónus à pontuação e mostrar a nova pontuação total, e depois esperar que o jogador prima uma tecla para iniciar o nível seguinte.

EVENT COLLECTBLOCK

SCORE 100                  	; score 100 points when we collect a Bone
AT 0 6 
SHOWSCORE			; display the score

SUBTRACT 1 FROM B	; decrement the number of bones left on screen
IF B = 0                ; have all Bones been collected?
   CLS                  ; clear the screen
   AT 10 2              ; at line 10, column 2...
   SHOWSCORE            ; display the score
   DELAY 25             ; wait 1 second
   PRINT " + "          ; display +
   DELAY 25             ; wait another second
   SHOWBONUS            ; display the bonus
   DELAY 25             ; wait another second
   PRINT " = "          ; display =
   DELAY 25             ; wait another second
   ADDBONUS             ; add the bonus to the score
   ZEROBONUS            ; reset the bonus to 0 now we've added it
   SHOWSCORE            ; display the new score
   AT 15 8              ; at line 15 column 8
   PRINT "PRESS KEY TO START"
   WAITKEY              ; wait for a key press
   NEXTLEVEL            ; if so move to the next screen
ENDIF

Vamos experimentar...

Pareceu funcionar... mas reparaste no problema?

Mesmo no final, quando o nível seguinte começou, a barra superior desapareceu completamente. Mas depois o valor da pontuação e o das vidas regressam...

Porque é que isto acontece?

Bem, primeiro usámos o comando CLS quando o Stinky Dog recolhe o último osso. O CLS limpa completamente o ecrã inteiro, por isso a barra de pontuação também vai embora.

Então, porque é que não é reposto quando começa o nível seguinte?

Em poucas palavras, a resposta é que o nosso código não lho diz. Neste momento colocamos o código PRINT "SCORE:" e PRINT "LIVES" no nosso evento GAME INITIALISATION. Este evento só é executado quando o jogo arranca pela primeira vez. A pontuação aparece quando recolhemos o primeiro osso, e as vidas aparecem quando somos mortos, porque temos os comandos SHOWSCORE e SHOWLIVES nos eventos COLLECTBLOCK e KILL PLAYER, respetivamente.

Para resolver isto, vamos mover os comandos PRINT para o evento RESTARTSCREEN. Este evento é executado sempre que reiniciamos um ecrã (incluindo depois de uma morte e quando começamos um nível novo).

Por isso, abre o teu script GAME INITIALISATION e corta tudo o que está abaixo de EVENT GAMEINIT, exceto LET LIVES = 3, de modo que agora deve ficar assim:

EVENT GAMEINIT

LET LIVES = 3

Depois abre o teu evento RESTART SCREEN e cola o código por cima da instrução DATA... agora deve ficar assim:

EVENT RESTARTSCREEN
RESTORE
READ B              ; read the first value of the DATA and put it in B
IF SCREEN >= 1      ; if it is screen 1 or above
   REPEAT SCREEN    ; then repeat SCREEN-many times
   READ B           ; read the next value
   ENDREPEAT        ; so we've found the right B value for the Screen
ENDIF

AT 0 0 
PRINT "SCORE:"
AT 0 6
SHOWSCORE

AT 0 21
PRINT "LIVES:"
DISPLAY DOUBLEDIGITS LIVES


;-------------------number of Bones per screen-------------------------
DATA 5 7 3 4 6 9 5 8 5 6 4 8 6 9 3 8 9
DATA 4 7 8 10 

Deixamos a instrução LET LIVES = 3 em Game initialisation porque só queremos que seja executada uma vez, quando o jogo arranca pela primeira vez. Se a puséssemos no evento RESTARTSCREEN, o número de vidas seria reposto sempre que o ecrã fosse reiniciado.

A variável de vidas no MPAGD pode conter um número de 8 bits (0-255) e, ao contrário de SCORE e BONUS, podemos escrever código à volta dela. Por exemplo, podíamos usar 'ADD 1 TO LIVES' se o jogador recolhesse um objeto em particular.

Comporta-se de forma um pouco diferente das variáveis normais: se chegar a 0 (sem vidas restantes), o MPAGD executa o evento 'LOST GAME'.

Como LIVES é uma variável de 8 bits, também precisamos de usar o comando DISPLAY para a mostrar.

O comando DISPLAY também tem parâmetros adicionais que podemos usar para controlar a forma como é apresentado no ecrã. São estes: DISPLAY SINGLEDIGIT: só mostrará de 0 a 9,

DISPLAY DOUBLEDIGITS: só mostrará de 0 a 99, com um 0 à frente de 0 a 9 (00, 01, 02, etc.)

DISPLAY TRIPLEDIGITS: mostrará de 0 a 255, com 00 à frente de 0 a 9 e um 0 à frente de 10 a 99

No nosso jogo vou limitar o número de vidas que se podem ganhar a um máximo de 10, por isso acrescentei o parâmetro DOUBLEDIGITS ao comando no código acima (realçado). Quanto à forma de limitar as vidas a um máximo de 10... voltamos a isso mais tarde.

Como usámos DOUBLEDIGITS para mostrar as vidas no evento RESTARTSCREEN, vamos precisar de fazer o mesmo sempre que o nosso código diga ao jogo para mostrar as vidas. Neste momento, só deve haver outra referência a LIVES, que está no nosso evento KILL PLAYER, que é ativado sempre que matamos o jogador. Abre o teu evento KILL PLAYER e acrescenta DOUBLEDIGITS...

EVENT KILLPLAYER


SUBTRACT 1 FROM LIVES
AT 0 27
DISPLAY DOUBLEDIGITS LIVES
ZEROBONUS

Também quero ajustar um pouco o jogo, por isso acrescentei ZEROBONUS ao evento KILLPLAYER. Assim, se o Stinky Dog for morto, perde as bonificações de pum que tenha acumulado.

Vamos testar o jogo...

Ok, parece que funciona como esperado, mas não gosto muito do tipo de letra nem das cores à volta da área de jogo. Acho que já é altura de tratarmos disso...

SEGUINTE: PARTE 21: Alterar tipos de letra, COLOUR, PAPER, INK e CLUT

Todo o MPAGD Iniciantes