Comecei esta série como uma pequena homenagem nostálgica ao Arcadia da Imagine, um jogo de que eu gostava muito aos 12 anos, em 1982. Se te lembras, no Arcadia original não era preciso matar todos os inimigos de cada vaga, era preciso sobreviver ao temporizador.
Podia implementar a mesma jogabilidade neste jogo com um temporizador, mas não estou a tentar recriar o Arcadia exatamente, por isso acho que vamos fazer outra coisa.
Como alternativa, podíamos fazer com que tenhas de matar todos os inimigos de cada vaga antes de aparecer a seguinte.
Ou talvez fosse boa ideia haver uma quantidade fixa de inimigos por vaga e, depois de todos terem sido gerados, começar a vaga seguinte. Assim, para obteres a pontuação máxima tens de matar o maior número possível e, talvez, se matares todos os inimigos de uma vaga haja algum tipo de bónus ou melhoria como recompensa.
Acho que esta última abordagem é a minha preferida e é a que vou tentar para começar.
Para isso, vamos precisar de uma variável que conte os inimigos de cada vaga que já matámos. Voltemos ao código do evento do nosso Spawner (Sprite Type 7)
e acrescentemos as linhas de código destacadas abaixo.
EVENT SPRITETYPE7 ; SPAWNER ; ============ IF SETTINGA = 0 ; first time we run this LET JUMPSPEED = 0 ; reset the enemies spawned counter LET SETTINGB = 0 ; reset the timer RESTORE ; start from the beginning of the data table REPEAT L ; get the data for this level READ AIRBORNE ; get the spawner movement READ X ; get starting x position READ Y ; get starting y position READ J ; get the enemy sprite type READ K ; get the enemy image READ E ; how many enemies in this level? READ G ; delay between releasing each enemy READ P ; Number of points scored if enemy is killed ENDREPEAT LET D = E ; store the number of enemies to be killed in D LET F = E ; also store #enemies in F to count kills & exits ADD 1 TO SETTINGA ; prevent this running again ENDIF IF SETTINGB = G ; has timer reached the delay point? IF JUMPSPEED < E ; are there still enemies left to spawn? IF S <= 8 ; are there 10 or less enemies already on screen? SPAWN J K ; spawn an enemy ADD 1 TO JUMPSPEED ; increment the number spawned SPAWNED ; switch to the enemy sprite LET DIRECTION = 0 ; set its initial direction to 0 ENDSPRITE ; return to the spawner ENDIF ELSE ; all enemies in this level have been spawned IF F = 0 ; if all enemies killed or exited ADD 1 TO L ; get ready for next level IF L = 3 ; have we reached the end of the levels? LET L = 1 ; yes, start again ENDIF LET SETTINGA = 0 ; GET DATA FOR NEXT LEVEL ENDIF ENDIF LET SETTINGB = 0 ; reset the timer ENDIF ADD 1 TO SETTINGB ; increment the timer DATA 0 165 8 2 2 5 12 5 0 80 8 2 2 5 12 10
Assim, lemos para E o número total de inimigos da vaga. Não vamos querer alterar esta informação durante a vaga, por isso vamos copiá-la para outra variável, D, que usaremos como contagem decrescente sempre que matarmos um inimigo.
Vamos também guardar o número de inimigos da vaga em F, e depois decrementar F sempre que um inimigo for morto ou sair do ecrã. Só passaremos ao nível / vaga seguinte quando todos os inimigos tiverem sido removidos do ecrã; caso contrário, poderíamos ter problemas, já que as vagas novas apareceriam antes de o último dos inimigos anteriores ter saído do ecrã, o que poderia estragar os nossos contadores.
Também temos de pensar no sistema de pontuação. No Arcadia, cada inimigo valia tantos pontos como o número do nível / vaga. Assim, no nível 1 cada morte valia 1 ponto, no nível 2 valia 2 pontos, e assim por diante.
Podíamos fazer o mesmo aqui com facilidade, mas, mais uma vez, não estou a tentar recriar o Arcadia exatamente e quero manter alguma flexibilidade, por isso vamos usar uma variável nova, P, que leremos da tabela DATA. Como podes ver no código destacado acima, matar um inimigo no nível 1 dará 5 pontos e matar um inimigo no nível 2 dará 10 pontos.
Também precisamos de mostrar a pontuação no ecrã. Primeiro vamos colocá-la no nosso evento RESTART SCREEN:
EVENT RESTARTSCREEN LET S = 0 ; initialise the sprite counter AT 0 1 ; position the cursor at Line 0 Column 1 SHOWSCORE ; display the score
Isto serve para começar, mas precisamos que se atualize sempre que se marcam pontos. Podíamos simplesmente colocar o mesmo código no MAIN LOOP, mas na minha experiência, se queres que o teu jogo de MPAGD funcione com eficiência, o melhor é não atualizar no ecrã as pontuações e variáveis em cada ciclo, mas sim apenas quando for necessário.
Uma abordagem seria repetir as linhas de código acima em todos os eventos em que se marcam pontos, mas isso poderia tornar-se bastante repetitivo em termos de código. Em vez disso, prefiro usar uma variável como gatilho, e vou usar T.
Agora, no nosso Main Loop 1 vamos acrescentar algum código:
EVENT MAINLOOP1 IF T = 1 ; Score bar update requested AT 0 1 ; at Line 0 column 1 SHOWSCORE ; update the score LET T = 0 ; reset the trigger ENDIF
Assim, sempre que quisermos atualizar a barra de pontuação, bastará acrescentar LET T = 1 nos eventos relevantes.
Voltemos ao evento do nosso sprite de explosão (Type 6) e acrescentemos os gatilhos, as contagens decrescentes e o código da pontuação:
EVENT SPRITETYPE6 ANIMATE ; regular amination IF FRAME = 4 ; are we on the last frame? IF DIRECTION = 0 ; was enemy hit by a torpedo? REMOVE ; yes, remove this sprite SUBTRACT 1 FROM S ; decrement the sprite counter SUBTRACT 1 FROM D ; decrement the enemy kill countdown SUBTRACT 1 FROM F ; decrement the kill/exit countdown IF D = 0 ; have all enemies been killed? SCORE 500 ; yes, score extra 500 points ELSE ; no, still some more to kill SCORE P ; score P number of points ENDIF ELSE IF DIRECTION = 1 ; is this the player exploding? KILL ENDIF ENDIF LET T = 1 ; update the score bar ENDIF
Agora vamos pontuar P pontos por cada morte, mas se matarmos todos os inimigos de uma vaga, D será 0 e ganharemos um bónus de 500 pontos.
Vamos testar...
Parece-me bem, o bónus está a funcionar como esperado.
Mas estes inimigos são um pouco inofensivos, por isso a seguir vamos dar-lhes armas próprias.
SEGUINTE: PARTE 8 : OS EXTRATERRESTRES CONTRA-ATACAM!
