Imagina que no teu jogo queres dar ao jogador um tempo fixo para completar cada ecrã. E depois, talvez, dar-lhe um bónus consoante o tempo que lhe sobrar quando cumprir com sucesso os objetivos dos níveis.
Como faríamos isso?
Primeiro, o MPAGD funciona a 25 frames por segundo, por isso deve ser bastante simples criar um mecanismo de temporização que conte segundos.
Segundo, vamos precisar de algumas variáveis para guardar (e mostrar) a quantidade atual de minutos/segundos restantes.
Terceiro, talvez queiramos mudar o tempo permitido ecrã a ecrã, ou talvez usar níveis de dificuldade para alterar o tempo permitido.
MÉTODO 1: Simples: o mesmo tempo em cada ecrã
Vamos começar com uma versão simples, em que cada ecrã tem uma quantidade fixa de segundos e minutos para ser completado; se o temporizador chegar a 0, o jogador morre.
Bem, o MPAGD funciona a 25 frames por segundo. Assim, se tivermos uma variável que é incrementada uma vez por frame, quando chegar a 25 teremos cronometrado um segundo.
Vamos usar a variável G como o nosso tempo geral, contando 1/25 de segundo.
Vamos também precisar de variáveis que guardem o número de minutos e segundos permitidos por ecrã:
M = Minutos
S = Segundos.
Vamos inicializar os valores destas três variáveis no nosso evento RESTART SCREEN; assim, serão repostos sempre que começarmos um ecrã, incluindo depois de uma morte. No teu evento restart screen vais adicionar:
LET G = 0 ; reset the 1/25s timer LET M = 1 ; countdown minutes allowed LET S = 0 ; countdown seconds allowed
A seguir, vamos acrescentar código que faz e mostra a contagem decrescente. Para garantir que é executado de forma consistente durante todo o jogo, vamos colocá-lo no evento MAINLOOP 1, para que seja executado no início de cada frame:
; COUNTDOWN TIMER
;================
ADD 1 TO G ; increment the general timer
IF G = 25 ; when it reaches 25
LET G = 0 ; reset it
SUBTRACT 1 FROM S ; decrement seconds remaining
ENDIF
IF S = 0 ; if 0 seconds
IF M = 0 ; and 0 minutes left
KILL ; kill the player
EXIT ; exit processing this event
ENDIF
SUBTRACT 1 FROM M ; decrement the minutes
LET S = 59 ; reset the seconds
ENDIF
COLOUR 71 ; white text on black (zx spectrum)
AT 22 26
DISPLAY DOUBLEDIGITS M ; display minutes remaining
CHR 58 ; ':'
DISPLAY DOUBLEDIGITS S ; display seconds remainingAssim, incrementamos G; quando chega a 25 repomos a 0 e decrementamos o número de segundos (S); quando S chega a 0 repomos a 59 e decrementamos o número de minutos, a não ser que já não haja minutos, caso em que o tempo acabou e matamos o jogador. É assim que deve ficar...
MÉTODO 2: Avançado: tempo diferente por ecrã
Se quisermos alterar o tempo disponível, só temos de mudar o código de inicialização de variáveis do nosso evento RESTART SCREEN para usar uma tabela DATA e fazer READ dos valores de Minutos (M) e Segundos (S)
Podemos usar isto para a inicialização de variáveis em RESTART SCREEN
LET G = 0 ; reset the 1/25s timer RESTORE ; restore the data table so we read from the start READ M ; read the 1st data and put it in M READ S ; read 2nd value put it in S IF SCREEN >= 1 ; if it is screen 1 or above REPEAT SCREEN ; then repeat SCREEN-many times READ M ; read the next value for M READ S ; and the next value for S ENDREPEAT ; so we've found the right M & S values for the Screen ENDIF
Depois vamos adicionar isto como a nossa tabela DATA; os valores alternam entre minutos e segundos, por isso o tempo permitido no SCREEN 0 é 0 minutos e 30 segundos (os 2 primeiros valores), para o SCREEN 1 é 1 minuto e 0 segundos (valores 3 e 4), para o Screen 2 é 1 minuto e 15 segundos (valores 5 e 6), e assim sucessivamente.
DATA 0 30 1 0 1 15 2 0 1 45 1 30 1 0 1 30
Adicionar um bónus por completar o ecrã
Tudo o que fizemos até agora serve para matar o jogador se o tempo acabar, mas e se ele cumprir os objetivos do ecrã? Poderíamos acrescentar um bónus com base no tempo restante. Dependendo do que ativa a conclusão do ecrã (no Stinky Dog é apanhar todos os ossos), vais ter de adicionar a tua rotina de bónus no evento correto. Pode ser algo como isto:
IF M > 0 ; if there are minutes left
REPEAT M ; repeat for each minute remaining
REPEAT 60 ; repeat 60 times (60 sec)
BONUS 10 ; increase bonus by 10
ENDREPEAT
ENDREPEAT
ENDIF
IF S > 0 ; if there are seconds left
REPEAT S ; repeat for each second
BONUS 10 ; increase the bonus by 10
ENDREPEAT
ENDIF
ADDBONUS ; add the bonus to the score
ZEROBONUS ; reset bonus to zeroAplicar isto ao nosso jogo Stinky Dog
No nosso jogo Stinky Dog, no entanto, há algumas alterações que quero fazer.
Primeiro, já temos uma tabela DATA em RESTART SCREEN 0, que guarda o número de ossos que têm de ser apanhados por ecrã. Sem problema, o MPAGD não quer saber que dados guarda na tabela DATA, por isso só temos de incluir os valores dos ossos e fazer READ três vezes por ciclo para obter o número correto de ossos, minutos e segundos.
LET G = 0 ; reset the 1/25s timer RESTORE ; restore the data table so we read from the start READ M ; read the 1st data and put it in M READ S ; read 2nd value put it in S READ B ; read third value and put it in B for Bones IF SCREEN >= 1 ; if it is screen 1 or above REPEAT SCREEN ; then repeat SCREEN-many times READ M ; read the next value for M READ S ; and the next value for S READ B ; and the next values for B ENDREPEAT ; we've found the right M, S & B values for the Screen ENDIF
E a tabela DATA no fim de RESTART SCREEN:
DATA 0 30 6 1 0 7 1 15 3 2 0 4 1 45 6 1 DATA 30 4 1 0 8 1 30 6
A seguir, como já criámos uma rotina de morte reutilizável que chamamos ao definir o valor SETTINGA do Stinky Dog como 99, vou mover o código do temporizador de contagem decrescente de MAINLOOP 1 para o evento do jogador, remover o comando KILL e mudá-lo para LET SETTINGA = 99
NOTA: Coloca o código DEPOIS da tua rotina IF SETTINGA = 99 ....ENDIF
; COUNTDOWN TIMER
;================
ADD 1 TO G ; increment the general timer
IF G = 25 ; when it reaches 25
LET G = 0 ; reset it
SUBTRACT 1 FROM S ; decrement seconds remaining
ENDIF
IF S = 0 ; if 0 seconds
IF M = 0 ; and 0 minutes left
LET SETTINGA = 99 ; kill the player
EXIT ; exit processing this event
ENDIF
SUBTRACT 1 FROM M ; decrement the minutes
LET S = 59 ; reset the seconds
ENDIF
COLOUR 71 ; white text on black (zx spectrum)
AT 22 26
DISPLAY DOUBLEDIGITS M ; display minutes remaining
CHR 58 ; ':'
DISPLAY DOUBLEDIGITS S ; display seconds remaining
Aqui está em acção quando ficamos sem tempo
Para adicionar uma nova bonificação de tempo ao completar o ecrã, vamos ter de actualizar o nosso evento COLLECT BLOCK:
EVENT COLLECTBLOCK
SCORE 100 ; score 100 points when we collect a Bone
AT 0 6
COLOUR 71
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 4 6
MESSAGE 1 ; "well done"
CHR 32
MESSAGE 0 ; "stinky dog"
CHR 33
DELAY 25 ; wait another second
COLOUR 65 ; bright blue on balck
AT 7 7
MESSAGE 2 ; "score"
CHR 32 ; <space>
DELAY 25 ; wait another second
SHOWSCORE
DELAY 25 ; wait another second
AT 9 2
COLOUR 70 ; bright yellow on black
MESSAGE 3 ; "fart"
CHR 32 ; <space>
MESSAGE 4 ; "bonus"
CHR 32 ; <space>
DELAY 25 ; wait another second
SHOWBONUS ; display the bonus
ADDBONUS ; add the bonus to the score
ZEROBONUS ; reset the bonus to 0 now we've added it
DELAY 25 ; wait another second
COLOUR 67 ; bright magenta on black
AT 11 2
MESSAGE 7 ; "time"
CHR 32 ; <space>
MESSAGE 4 ; "bonus"
CHR 32 ; <space>
DELAY 25 ; wait another second
IF M > 0 ; if there are minutes left
REPEAT M ; repeat for each minute remaining
REPEAT 60 ; repeat 60 times (60 sec)
BONUS 10 ; increase bonus by 10
ENDREPEAT
ENDREPEAT
ENDIF
IF S > 0 ; if there are seconds left
REPEAT S ; repeat for each second
BONUS 10 ; increase the bonus by 10
ENDREPEAT
ENDIF
SHOWBONUS
ADDBONUS ; add the bonus to the score
ZEROBONUS ; reset bonus to zero
AT 13 5
COLOUR 71
MESSAGE 8 ; "total"
CHR 32
CHR 61
CHR 32
SHOWSCORE ; display the score
DELAY 25 ; wait 1 second
AT 17 8 ; at line 15 column 8
COLOUR 215
MESSAGE 5 ; "press key to start"
WAITKEY ; wait for a key press
NEXTLEVEL ; if so move to the next screen
ENDIFRepara que adicionei duas mensagens novas aos TEXT MESSAGES:
DEFINEMESSAGES "STINKY DOG" ;0 "WELL DONE" ;1 "SCORE" ;2 "FART" ;3 "BONUS" ;4 "PRESS KEY TO START" ;5 "LIVES" ;6 "TIME" ;7 "TOTAL" ;8
Aqui está tudo a funcionar às mil maravilhas!
