Até agora temos duas vagas de extraterrestres e são bastante fáceis de derrotar, mas vejo um problema na forma como o escrevemos. No jogo espero ter muitos padrões de movimento diferentes para os extraterrestres, estou a pensar num estilo Galaga, ou pelo menos nas partes em que os extraterrestres entram a voar no ecrã.
Com o nosso padrão inicial de extraterrestres houve algum grau de reutilização de código, mas acho que podemos aproveitar mesmo os comandos DATA & READ do MPAGD para chegar a uma abordagem muito mais flexível, que nos poderia ajudar a criar rapidamente infinitos padrões de movimento de extraterrestres (ou pelo menos até ficarmos sem memória!
Primeiro vou criar um sprite novo de nave extraterrestre:

Vou começar um Sprite Type novo para os meus novos extraterrestres flexíveis... Vou usar o Sprite Type 5.
Pensemos nas direções possíveis em que um extraterrestre se pode mover. Acho que as 16 direções alargadas da rosa dos ventos nos darão flexibilidade suficiente:

Depois vamos escrever código de movimento para cada ponto cardeal, usando a variável local DIRECTION, começando em 0 para N, 1 para NNE e assim sucessivamente no sentido dos ponteiros do relógio:
EVENT SPRITETYPE5 ANIMATE SLOW ; FLEXI ALIENS ; ===================== IF DIRECTION = 0 ; Move N SPRITEUP SPRITEUP ENDIF IF DIRECTION = 1 ; Move NNE SPRITERIGHT SPRITEUP SPRITEUP ENDIF IF DIRECTION = 2 ; Move NE SPRITERIGHT SPRITERIGHT SPRITEUP SPRITEUP ENDIF IF DIRECTION = 3 ; Move ENE SPRITERIGHT SPRITERIGHT SPRITEUP ENDIF IF DIRECTION = 4 ; Move E SPRITERIGHT SPRITERIGHT ENDIF IF DIRECTION = 5 ; Move ESE SPRITERIGHT SPRITERIGHT SPRITEDOWN ENDIF IF DIRECTION = 6 ; MOVE SE SPRITERIGHT SPRITERIGHT SPRITEDOWN SPRITEDOWN ENDIF IF DIRECTION = 7 ; MOVE SSE SPRITEDOWN SPRITEDOWN SPRITERIGHT ENDIF IF DIRECTION = 8 ; MOVE S SPRITEDOWN SPRITEDOWN ENDIF IF DIRECTION = 9 ; MOVE SSW SPRITEDOWN SPRITEDOWN SPRITELEFT ENDIF IF DIRECTION = 10 ; MOVE SW SPRITEDOWN SPRITEDOWN SPRITELEFT SPRITELEFT ENDIF IF DIRECTION = 11 ; MOVE WSW SPRITEDOWN SPRITELEFT SPRITELEFT ENDIF IF DIRECTION = 12 ; MOVE W SPRITELEFT SPRITELEFT ENDIF IF DIRECTION = 13 ; MOVE WNW SPRITELEFT SPRITELEFT SPRITEUP ENDIF IF DIRECTION = 14 ; MOVE NW SPRITELEFT SPRITELEFT SPRITEUP SPRITEUP ENDIF IF DIRECTION = 15 ; MOVE NNW SPRITELEFT SPRITEUP SPRITEUP ENDIF
Muito bem, isto vai definir cada um dos movimentos possíveis de um extraterrestre. Agora só precisamos de uma forma de definir um padrão de movimentos, que podia ser tão simples como uma sequência de valores para DIRECTION e o número de repetições.
Assim, 8 20 significaria: executa a DIRECTION 8 (sul) 20 vezes.
Se te lembras do nosso método anterior para mover a primeira vaga de extraterrestres, iam para sul e depois desviavam-se para sudoeste,
No nosso método novo isso poderia ser representado assim:
8 20 (sul 20 vezes)
7 8 (SSE 8 vezes)
6 8 (SE 8 vezes)
5 8 (ESE 8 vezes)
4 16 (E 16 vezes)
O que se presta na perfeição a ser guardado numa tabela DATA, por exemplo:
DATA 8 20 7 8 6 8 5 8 4 16
Depois poderíamos criar facilmente padrões novos que descrevam o movimento dos extraterrestres de cada nível, apenas neste evento.
Isso deve ser mesmo eficiente!
Mas há algumas coisas de que vamos precisar para isto funcionar:
1) Uma variável para guardar o número de repetições da direção de movimento atual
2) Uma forma de encontrar o ponto de partida certo do padrão específico do nível / vaga.
O ponto 1 é bastante fácil de resolver: vamos simplesmente usar SETTINGB para ler para ela o número de repetições
Vamos usar SETTINGA como variável de controlo, para garantir que fazemos as coisas no momento certo
E vamos usar JUMPSPEED como contador do número de repetições.
Acrescenta o código destacado ao teu evento SPRITE TYPE 5:
EVENT SPRITETYPE5 ; FLEXI ALIENS ; ===================== SPRITEINK C ; Colour the aliens ; FIND THE STARTING POINT FOR THIS LEVEL ;======================================= IF SETTINGA = 0 ; Alien first appears RESTORE ; Restore the data table LET RND = L ; Store the Level number in RND ADD 50 TO RND ; and increase it by 50 WHILE DIRECTION <> RND ; While DIRECTION doesnt = RND READ DIRECTION ; Read value from DATA table READ SETTINGB ; Also read second value ENDWHILE ; Keep going until we find the value in RND LET SETTINGA = 1 ; When we find it change SA to 1 ENDIF ; GET THE NEXT DIRECTION & # REPETITIONS ;======================================= IF SETTINGA = 1 ; Ready to get direction & reptitions READ DIRECTION ; Read the next movement into DIRECTION READ SETTINGB ; Read the repetitions into SettingB LET JUMPSPEED = 0 ; reset the counter LET SETTINGA = 2 ; now we are ready to move ENDIF ; MOVEMENTS ;============== IF DIRECTION = 0 ; Move N SPRITEUP SPRITEUP ENDIF IF DIRECTION = 1 ; Move NNE SPRITERIGHT SPRITEUP SPRITEUP ENDIF IF DIRECTION = 2 ; Move NE SPRITERIGHT SPRITERIGHT SPRITEUP SPRITEUP ENDIF IF DIRECTION = 3 ; Move ENE SPRITERIGHT SPRITERIGHT SPRITEUP ENDIF IF DIRECTION = 4 ; Move E SPRITERIGHT SPRITERIGHT ENDIF IF DIRECTION = 5 ; Move ESE SPRITERIGHT SPRITERIGHT SPRITEDOWN ENDIF IF DIRECTION = 6 ; MOVE SE SPRITERIGHT SPRITERIGHT SPRITEDOWN SPRITEDOWN ENDIF IF DIRECTION = 7 ; MOVE SSE SPRITEDOWN SPRITEDOWN SPRITERIGHT ENDIF IF DIRECTION = 8 ; MOVE S SPRITEDOWN SPRITEDOWN ENDIF IF DIRECTION = 9 ; MOVE SSW SPRITEDOWN SPRITEDOWN SPRITELEFT ENDIF IF DIRECTION = 10 ; MOVE SW SPRITEDOWN SPRITEDOWN SPRITELEFT SPRITELEFT ENDIF IF DIRECTION = 11 ; MOVE WSW SPRITEDOWN SPRITELEFT SPRITELEFT ENDIF IF DIRECTION = 12 ; MOVE W SPRITELEFT SPRITELEFT ENDIF IF DIRECTION = 13 ; MOVE WNW SPRITELEFT SPRITELEFT SPRITEUP ENDIF IF DIRECTION = 14 ; MOVE NW SPRITELEFT SPRITELEFT SPRITEUP SPRITEUP ENDIF IF DIRECTION = 15 ; MOVE NNW SPRITELEFT SPRITEUP SPRITEUP ENDIF ; BOUNDARY CHECKING ; =================== IF X <= LEFTEDGE ; if alien reaches the left edge REMOVE ; remove it SUBTRACT 1 FROM S ; decrement the sprite counter SUBTRACT 1 FROM F ; decrement the number of aliens still in ENDIF IF X >= RIGHTEDGE ; if alien reaches the right edge REMOVE ; remove it SUBTRACT 1 FROM S ; decrement the sprite counter SUBTRACT 1 FROM F ; decrement the number of aliens still in ENDIF IF Y >= BOTTOMEDGE ; if alien reaches the right edge REMOVE ; remove it SUBTRACT 1 FROM S ; decrement the sprite counter SUBTRACT 1 FROM F ; decrement the number of aliens still in ENDIF ; INCREMENT REPETITION COUNTER & CHECK IF WE NEED NEXT DIRECTION ;============================== SUBTRACT 1 FROM SETTINGB ; decrement the number of repetitions IF SETTINGB = 0 ; have we done all the required repetitions LET SETTINGA = 1 ; yes, request the next direction ENDIF ; MOVEMENT & REPETITIONS DATA TABLE DATA 51 0 8 20 7 8 6 8 5 8 4 16 DATA 5e2 0 8 20 9 8 10 8 11 8 12 16
Primeiro, acrescentei um comando spriteink para colorir os extraterrestres com o valor C (vamos acrescentá-lo à tabela de dados do spawner daqui a pouco)
Assim, quando este evento for executado pela primeira vez para um sprite extraterrestre, SettingA será 0 (vamos ter de o acrescentar a Initialise Sprites daqui a pouco)
Isto vai restaurar a tabela de dados (o que significa que o READ seguinte será o primeiro valor da tabela). Depois vamos percorrer os dados até encontrarmos um valor igual a 50 + o número do nível (ou seja, para o nível 1 procuramos 51, para o nível 2 procuramos 52 e assim sucessivamente).
Escolhi 50 porque é pouco provável que precise de mais de 50 direções (0-15 representam os nossos 16 pontos cardeais), mas deixa-me margem para acrescentar mais depois e significa que poderia ter mais de 200 padrões de movimento neste evento, o que deverá ser mais do que suficiente.
Depois de o encontrarmos, vamos ler o número seguinte para SETTINGB (vamos usar apenas 0) e depois pôr SettingA a 1 para não restaurarmos os dados em cada ciclo.
É importante perceber que cada sprite sabe sempre até onde leu da tabela de dados, a menos que façamos um RESTORE, momento em que volta ao início.
Agora que SettingA é 1, vamos fazer um READ do número de DIRECTION e do número de REPETITIONS necessárias para SETTINGB, e depois pômos settingA a 2 para impedir que isto volte a ser executado até todas as repetições da direção de movimento terem sido realizadas.
Repara que também coloquei uma verificação de limites (não muito eficiente, vamos melhorá-la mais tarde) que removerá os extraterrestres que saiam do ecrã.
Por fim, temos a nossa tabela DATA. De momento limitei-me a replicar os nossos dois padrões de movimento originais: descer e desviar para a direita, e descer e desviar para a esquerda.
Muito bem, antes de o testarmos temos mais algumas tarefas para concluir.
MENU: EVENTS > INITIALISE SPRITES:
EVENT INITSPRITE ADD 1 TO S ; increment the sprite counter IF TYPE 1 ; PHOTON TORPEDO LET SETTINGB = 0 ; initialise the distance counter ENDIF IF TYPE 5 ; FLEXI ALIENS LET SETTINGA = 0 ; Initialise SettingA ENDIF IF TYPE 7 ; SPAWNER LET SETTINGA = 0 ; RESET SETTINGA ENDIF
A seguir, vamos atualizar o código do evento do Spawner:
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 READ C ; get the colour value for the alien 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 132 8 5 2 8 8 5 67 DATA 0 100 8 5 2 8 8 10 68
Aqui acrescentei um valor novo a cada conjunto de dados e separei os dois níveis em linhas próprias para ser mais fácil de ler. O valor novo (o nono) é o que será lido para C.
Acho que estamos prontos para testar! Vamos compilar este petiz!
Sim! Olha como eles voam!
Muito bem, agora vamos divertir-nos e criar alguns padrões novos na tabela DATA do sprite type 5. Garante que começas cada padrão com 200+Nível# seguido de um zero e depois os teus pares de DIRECTION # e Repetition #
Experimenta estes para começar, e depois inventa os teus:
Substitui a tabela DATA do teu evento de extraterrestre (Sprite Type 5) por:
DATA 51 0 8 20 7 8 6 8 5 8 4 16 DATA 52 0 8 20 9 8 10 8 11 8 12 16 DATA 53 0 12 48 11 2 10 2 9 2 8 2 7 2 6 2 5 2 4 40 5 2 6 2 7 2 8 2 9 2 10 40 DATA 54 0 4 48 5 2 6 2 7 2 8 2 9 2 10 2 11 2 12 40 11 2 10 2 9 2 8 2 7 2 6 40 DATA 55 0 13 26 14 4 15 4 0 4 1 4 2 4 3 4 4 4 5 4 6 4 7 4 8 4 9 4 10 40 DATA 56 0 3 26 1 4 0 4 15 4 14 4 13 4 12 4 11 4 10 4 9 4 8 4 7 4 6 40
E substitui a tabela de dados do teu Spawner (Sprite Type 7) por:
DATA 0 132 8 5 2 8 8 5 67 DATA 0 100 8 5 2 8 8 10 68 DATA 0 232 16 5 5 8 6 15 69 DATA 0 8 16 5 5 8 6 15 70 DATA 0 232 146 5 2 16 6 20 71 DATA 0 8 146 5 2 16 6 20 66
Agora que temos 6 vagas de ataque / níveis, vais ter de atualizar esta linha no evento do teu spawner
IF L = 3 ; have we reached the end of the levels?
para:
IF L = 7 ; have we reached the end of the levels?
Guarda o teu jogo, e vamos compilá-lo e disparar a alguns extraterrestres!
Fixe! Sente-te à vontade para experimentar e criar muitos mais padrões de ataque!
No entanto, já está na altura de dar aos extraterrestres armas próprias. Se nos apoiarmos na estrutura que já criámos e usarmos alguns dos truques que aprendemos, deveremos conseguir acrescentar muito mais variedade ao jogo.
SEGUINTE: Parte 9: Os extraterrestres contra-atacam!
