Curso de Jogos em Basic
Movimentos e animações de objetos


  Uma vez pronto o cenário e os personagens e descobrirmos como tratar eventos, vamos colocar os personagens e objetos do jogo em movimento.

  Nesse capítulo iremos estudar como realizar o movimento de um personagem pela tela, bem como introduzir uma animação de movimento e/ou resposta a evento, de forma a deixar o jogo mais realista.
5.1. Movimento de objetos   A movimentação do personagem controlado pelo jogador é bem simples, pois consiste em captar os comandos transmitidos pelo jogador via teclado ou joystick e repassá-los ao personagem.
  Há várias formas de se captar os comandos do jogador, que foram discutidos no curso de Basic, capítulo Teclado e Joystick, bem como nos capítulos anteriores desse curso.

  Nossa missão agora é descobrir uma maneira de controlar os demais personagens/objetos em cena. Para isso, necessitamos de alguns conceitos de inteligência artificial.
5.1.1. Movimento mecânico   A movimentação mecânica consiste em imprimir um movimento definido ao personagem, utilizando-se uma fórmula matemática ou uma lei da Física. Podemos também controlar se o personagem ultrapassa os limites de sua área de ação ou não, deixando assim que ele passe o limite da tela e retorne ao inicio dela.

  No exemplo a seguir, deslocaremos uma bola sobre a plataforma. A cada iteração do loop, adicionamos um deslocamento DX à coordenada X. Além disso, controlamos para que ela não ultrapasse os limites da plataforma. Ao atingir as bordas, o deslocamento DX tem seu sentido invertido (DX=-DX).
10 SCREEN 2
20 OPEN"GRP:" AS #1
30 X=40:Y=94:DX=1
40 LINE(30,102)-(100,109),6,BF:'Plataforma
50 FOR I=1 TO 8
60 READ A$
70 S$=S$+CHR$(VAL("&H"+A$))
80 NEXT I
90 SPRITE$(0)=S$
100 PUT SPRITE 1,(X,Y-1),12,0
110 X=X+DX
120 IF X<30 OR X>92 THEN DX=-DX
130 GOTO 100
300 DATA 3C,7E,FF,FF,FF,FF,7E,3C

  No jogo Treasures diving, todos os peixes são controlados pela mesmas variáveis VX e VY. Assim, as diferentes posições dos peixes é calculada da seguinte forma:
Coordenada_X_do_peixe_n = VX * Velocidade + Deslocamento
Coordenada_Y_do_peixe_n = VY + Deslocamento
  A cada iteração do loop, VX é decrescido de 2 unidades. A velocidade normal é 1.

  As trajetórias dos peixes são retilíneas e passam do limite da tela, retornando do lado oposto. De modo a torná-la mais real, poderíamos implementar uma pequena oscilação em VY. Outro fato interessante é que pelas trajetórias definidas dos peixes, eles nunca se encontram. Além disso, o tesouro é desenhado e não é um sprite. Assim, o tratamento ON SPRITE GOSUB fica exclusivamente para o encontro entre o mergulhador e um peixe.
5.1.2. Movimento aleatório   Uma estratégia para movimentação dos personagens é atribuir uma direção aleatória.

  Porém, não basta simplesmente calcular aleatoriamente uma direção, pois faria do objeto como um "carro desgovernado". Veja o exemplo a seguir.
10 SCREEN 2
20 OPEN"GRP:" AS #1
30 X=40:Y=94:DX=1
40 FOR I=1 TO 8
50 READ A$
60 S$=S$+CHR$(VAL("&H"+A$))
70 NEXT I
80 SPRITE$(0)=S$
90 PUT SPRITE 1,(X,Y-1),12,0
100 X=X+RND(-TIME)*9-4
110 Y=Y+RND(-TIME)*9-4
120 GOTO 90
300 DATA 3C,7E,FF,FF,FF,FF,7E,3C
  A bolinha vai a qualquer direção, sem esboçar qualquer movimento inteligente.

  No jogo Lock-in Man, a movimentação dos fantasmas é feita de forma similar a essa, onde as variáveis PP e PR controlam a direção do próximo movimento. Nesse caso, um sentido aleatório é escolhido na direção norte-sul em uma iteração, enquanto que na iteração seguinte é escolhido um sentido para leste-oeste, alternando dessa maneira. Assim, a movimentação dos fantasmas parece algo muito aleatório, onde quase nunca perseguem você.

  O que melhora um pouco o desempenho dos fantasmas do jogo anterior em relação ao exemplo da bolinha maluca é que o labirinto irá guiar os fantasmas. No jogo, um teste é sempre feito para saber se a próxima posição é caminho livre ou parede, conforme visto no capítulo 2.
5.1.3. Movimento de perseguição   Os tipos de movimentos anteriores não levam em consideração a posição do personagem controlado pelo jogador. Quando calculamos as novas posições dos inimigos, tomando como base a posição atual do jogador, de forma a fazer com que o inimigo chegue cada vez mais perto dele, estamos realizando uma perseguição. A posição do jogador serve como um guia para o movimento dos inimigos, dando a impressão deles serem "inteligentes" e acompanhar você onde quer que você vá.

  Os jogos Break-man, Pucky e Q-Bert, todos publicados na revista holandesa MSX Computer Magazine, realizam seus movimentos com base na posição do jogador. Por exemplo, no jogo Break-man, uma rotina verifica a cada iteração se as coordenadas do robô são maiores ou menores que a do jogador.
210 IF V>X THEN RR=4
220 IF V<X THEN RR=2
230 IF W>Y THEN RR=1
240 IF W<Y THEN RR=3
  Onde as coordenadas do jogador são X,Y e do robô são V,W.

  Ao comparar as coordenadas, ele estabelece a direção (RR) que o robô deverá seguir. Olhando o código acima, ele primeiro verifica a direção leste-oeste (X vs V). Caso X seja diferente de V, ele se move para leste ou oeste no sentido do jogador. Ele somente se move para baixo, quando ambos estão alinhados no eixo X, ou seja, quando X=V.

  Já o jogo Pucky observa qual é a direção mais vantajosa para seguir. A linha 480 desse jogo contém as seguintes instruções:
YY=Y-AY
XX=X-AX
Q=-AA
W=-AB
IF ABS(YY)>=ABS(XX) THEN 
  AB=SGN(YY)
  AA=0
ELSE
  AB=0
  AA=SGN(XX)
  Onde X,Y são as coordenadas do jogador, enquanto que AX,AY as coordenadas do fantasma. A variável AA contém o deslocamento em AX e AB em AY.

  Ele calcula as distâncias entre X e AX, e Y e AY. Depois, verifica qual módulo de distância é maior. Se for em Y, move o fantasma na direção do eixo Y. Caso contrário, move o fantasma no eixo X.

  Outras estratégias de movimento podem ser encontradas no curso de AI.
5.2. Animação de objetos   A animação de objetos consiste simplesmente em alterar a forma desses objetos durante um movimento ou tempo decorrido. Não importa se estamos falando em shapes ou tiles, a estratégia é a mesma.

  O movimento de um personagem pode ser caracterizado por utilizar apenas uma forma para representá-lo. Esta é a forma mais "preguiçosa" de desenvolvimento de jogos, pois o MSX possui um enorme espaço para armazenar sprites, bem como realiza a troca rápida deles, mesmo no Basic. O resultado disso é uma movimentação estranha, que não responde às mudanças de direção ou a qualquer evento que ocorra em cima desse personagem. Por exemplo, se ele morre e fica com a mesma cara.

  Ao inserirmos animação nos personagens, o nosso jogo ganha vida! Entretanto, veremos antes mais algumas ferramentas para a criação de shapes para o MSX, que nos auxiliarão nos próximos exemplos.
5.2.1. Criando shapes com o MSX Sketch Tools - Aquarela   O formato shape do Aquarela é compatível com a tabela de padrões de shapes do MSX 1. Dessa forma, utilizaremos o programa MSX Sketch Tools - versão Aquarela para criar shapes para o MSX. O pacote executável da versão 1.1 vem com um gabarito contendo 64 quadrados brancos com 16x16 pixels. É só colar o desenho de cada shape nessas áreas.

  Para os exemplos da próxima seção, utilizaremos alguns shapes do jogo "Goonies", onde temos a animação do caminhar de um inimigo e da de um esqueleto.
  Há o movimento para as duas direções do boneco e do esqueleto. No caso do boneco, há também uma representação dele parado.

  Em seguida, utilizamos o executável Java "gif2aqu.class" do MSX Sketch Tools para converter esse gabarito para shape.
java gif2aqu -shape goonies.gif
  O resultado é o arquivo "goonies.spr", que contém o mapa da tabela de sprites com 64 posições.

  O que?! Eu posso carregar os sprites prontos, sem ter que desenvolver aqueles códigos complexos e me poupar um trabalhão?
  😲😲😲😲😲

  Sim! 😄😄😄😄😄

  Veja como carregar os sprites que criamos a seguir.
10 SCREEN 1,2
20 BLOAD"GOONIES.SPR",S
30 PUT SPRITE 0,(128,95),11,0
  A prova do que fizemos em três linhas, na figura a seguir.
5.2.2. Animação   Utilizando os shapes criados na seção anterior, vamos criar uma animação do boneco andando. Utilize os cursores direito e esquerdo para mover o boneco.
10 SCREEN 1,2
20 BLOAD"GOONIES.SPR",S
30 X=128:Y=95:DX=2:DR=1:WK=1
35 ' Mapa de movimentos x sprite
40 SP(1,1)=0:SP(1,2)=2:SP(2,1)=3:SP(2,2)=5
50 C=STICK(0)
60 PUT SPRITE 0,(X,Y),11,SP(DR,WK)
70 IF C=3 THEN X=X+DX : DR=1 : IF WK=1 THEN WK=2 ELSE WK=1
80 IF C=7 THEN X=X-DX : DR=2 : IF WK=1 THEN WK=2 ELSE WK=1
90 GOTO 50
  A variável DR controla a direção (1 →, 2 ←), enquanto que WK controla uma das duas animações do caminhar.
  Uma tabela que mapeia a direção e caminhar atual com o sprite correspondente foi criada na linha 40. O mapeamento é muito mais rápido do que calcular o sprite certo a cada interação.
  A cada toque no cursor o caminhar muda, assim como a direção é atualizada (linhas 70-80).

  Detecção do personagem parado

  Podemos detectar se o boneco parou e adicionar o sprite dele parado. É possível fazer isso de duas formas distintas: quando o valor da função STICK for zero ou através de uma varredura periódica com a instrução ON INTERVAL. Através dessa, podemos inserir animações interessantes, como o personagem batendo o pé porque o jogador demora a andar.

  No exemplo a seguir, o boneco altera o sprite para o desenho de parado quando o STICK for zero.
10 SCREEN 1,2
20 BLOAD"GOONIES.SPR",S
30 X=128:Y=95:DX=2:DR=1:WK=0
35 ' Mapa de movimentos x sprite
40 SP(1,0)=1:SP(2,0)=4:SP(1,1)=0:SP(1,2)=2:SP(2,1)=3:SP(2,2)=5
50 C=STICK(0)
60 PUT SPRITE 0,(X,Y),11,SP(DR,WK)
65 IF C=0 THEN WK=0
70 IF C=3 THEN X=X+DX : DR=1 : IF WK=1 THEN WK=2 ELSE WK=1
80 IF C=7 THEN X=X-DX : DR=2 : IF WK=1 THEN WK=2 ELSE WK=1
90 GOTO 50

  Através da instrução ON INTERVAL, faremos uma verificação periódica de forma a detectar se entre um intervalo e outro houve movimento.
10 SCREEN 1,2
20 BLOAD"GOONIES.SPR",S
30 X=128:Y=95:DX=2:DR=1:WK=1:LW=0
35 ' Mapa de movimentos x sprite
40 SP(1,0)=1:SP(2,0)=4:SP(1,1)=0:SP(1,2)=2:SP(2,1)=3:SP(2,2)=5
50 ON INTERVAL=10 GOSUB 200:INTERVAL ON
60 C=STICK(0)
70 PUT SPRITE 0,(X,Y),11,SP(DR,WK)
75 LW=WK
80 IF C=3 THEN X=X+DX : DR=1 : IF WK=1 THEN WK=2 ELSE WK=1
90 IF C=7 THEN X=X-DX : DR=2 : IF WK=1 THEN WK=2 ELSE WK=1
100 GOTO 60
200 ' Verifica 
210 IF WK=LW THEN WK=0
220 RETURN
  A variável LW armazena o último passo dado. Assim, quando WK=LW durante um intervalo de 10/60 segundos, ele troca a animação do caminhar pelo parado.

  Por fim, faremos uma animação do esqueleto andando sozinho de um lado para o outro.
10 SCREEN 1,2
20 BLOAD"GOONIES.SPR",S
30 X=10:Y=95:DX=1:DR=1:WK=1
40 ' Mapa de movimentos x sprite
50 SP(1,1)=6:SP(1,2)=7:SP(2,1)=8:SP(2,2)=9
60 PUT SPRITE 0,(X,Y),15,SP(DR,WK)
70 X=X+DX
80 IF X MOD 4=0 THEN IF WK=1 THEN WK=2 ELSE WK=1
90 IF X<0 OR X>245 THEN DX=-DX:IF DR=1 THEN DR=2 ELSE DR=1
100 GOTO 60
  Na linha 80, fazemos com que o desenho do sprite do passo troque a cada 4 pixels.




<< Anterior BasGame Próxima >>


/MARMSX/CURSOS/BasGame