Se você perdeu a parte anterior, acesse-a aqui: Parte 8
Primeiro, vamos corrigir o problema do aparecimento da linha do retângulo desenhado no sprite redesenhado, quando o primeiro se deslocava por trás do segundo. Além disso, vamos aproveitar para ler os três primeiros sprites, onde o personagem anda para baixo, e gravá-los em um vetor de sprites. Para fazer isso, vamos declarar novas variáveis e alterar a função spritesheet2.onload, conforme a seguir
var boySprite = []; var spriteChangeCounter = 0; var currentSprite = 0; ... spritesheet2.onload = function() { sx = canvas2.width-spritesheet2.width; sy = canvas2.height-spritesheet2.height; ctx2.drawImage(spritesheet2, canvas.width-spritesheet2.width, canvas.height-spritesheet2.height); for (currentSprite=0; currentSprite<3; currentSprite++) { boySprite.push(ctx2.getImageData(sx, sy+(84*currentSprite), 65, 84)); } currentSprite = 0; requestAnimationFrame(secondLoop); };
No código acima, transformamos a variável boySprite em um vetor, para gravarmos mais de um sprite. Além disso, a variável spriteChangeCounter foi criada para que um número de chamadas à função secondLoop, agendada a, aproximadamente, cada 16,67ms, seja feita antes de trocarmos o sprite. Caso contrário, trocaríamos o sprite a cada 16,67ms, o que é rápido demais, a não ser que tivéssemos uns trinta deles para cada movimento. Ainda, a variável currentSprite foi declarada para manter o índice do sprite atual. Então, o laço for criado lê uma subimagem da imagem, depois outra, 84 pixels abaixo, e, depois, a última, mais 84 pixels abaixo (valor que eu tive que determinar empiricamente), “empurrando” cada uma delas para dentro do vetor boySprite na linha 13. Além disso, o currentSprite é zerado na linha 16 para que a animação comece da primeira imagem. Finalmente, veja que drawImage foi utilizado nessa função para que a figura exista antes de ser lida pelo ctx2.getImageData. Anteriormente, isso era feito na função de redesenho, o que levava à leitura sucessiva do canvas, causando, também, a leitura do lado do retângulo móvel quando passava atrás da spritesheet. Assim, esse bug fica corrigido.
Agora, vamos à modificação na função de redesenho, secondLoop
function secondLoop(timestamp) { ctx2.clearRect(0, 0, canvas.width, canvas.height); x2 = x2 + dx2; if (x2 > canvas.width) { x2 = 0; } ctx2.strokeRect(x2, 20, 100, 200); ctx2.drawImage(spritesheet2, canvas.width-spritesheet2.width, canvas.height-spritesheet2.height); if (spriteChangeCounter == 10) { spriteChangeCounter = 0; currentSprite++; } else { spriteChangeCounter++; } ctx2.putImageData(boySprite[currentSprite%3], 0, 240); requestAnimationFrame(secondLoop); }
A estrutura condicional foi acrescentada a partir da linha 13 para permitir que o sprite seja trocado apenas a cada dez chamadas da função. Se quiser fazer um teste, altere o valor na linha 13 para cinco e, depois, para vinte, e veja a velocidade de atualização das sprites mudar. Por fim, vamos analisar o código para acessar cada subimagem do vetor, na linha 23. Perceba que o índice do vetor boySprite resulta do resto da divisão entre a variável currentSprite e o número três, que é o número de sprites para o movimento que estamos animando. Assim, veja a evolução do índice na tabela a seguir
currentSprite | Índice |
0 | 0 |
1 | 1 |
2 | 2 |
3 | 0 |
4 | 1 |
5 | 2 |
6 | 0 |
7 | 1 |
8 | 2 |
9 | 0 |
10 | 1 |
… | … |
Desse modo, através da troca de sprites da área dos subdesenhos, consegue-se a animação, que pode ser vista em
Fez algum teste interessante no código? Compartilhe nos comentários!
Até a próxima.
2 comentários sobre “HTML5/JavaScript para Jogos (Parte 9)”