<!DOCTYPE html>
<html>
<head>
<title>Personagem controlável e animado</title>
<script src="spritesheet.js"></script>
<script src="animacao.js"></script>
<script src="teclado.js"></script>
<script src="sonic.js"></script>
</head>
<body>
<canvas id="canvas_sonic" width="500" height="500"></canvas>
<script>
var canvas = document.getElementById('canvas_sonic');
var context = canvas.getContext('2d');
var teclado = new Teclado(document);
var animacao = new Animacao(context);
var imgSonic = new Image();
imgSonic.src = 'spritesheet.png';
var sonic = new Sonic(context, teclado, imgSonic);
sonic.x = 0;
sonic.y = 200;
animacao.novoSprite(sonic);
imgSonic.onload = function() {
animacao.ligar();
}
</script>
</body>
</html>
---------------------------------------------------------------------------------------------------
sonic.js
var SONIC_DIREITA = 1;
var SONIC_ESQUERDA = 2;
function Sonic(context, teclado, imagem) {
this.context = context;
this.teclado = teclado;
this.x = 0;
this.y = 0;
this.velocidade = 10;
// Criando a spritesheet a partir da imagem recebida
this.sheet = new Spritesheet(context, imagem, 3, 8);
this.sheet.intervalo = 60;
// Estado inicial
this.andando = false;
this.direcao = SONIC_DIREITA;
}
Sonic.prototype = {
atualizar: function() {
if (this.teclado.pressionada(SETA_DIREITA)) {
// Se já não estava neste estado...
if (! this.andando || this.direcao != SONIC_DIREITA) {
// Seleciono o quadro da spritesheet
this.sheet.linha = 1;
this.sheet.coluna = 0;
}
// Configuro o estado atual
this.andando = true;
this.direcao = SONIC_DIREITA;
// Neste estado, a animação da spritesheet deve rodar
this.sheet.proximoQuadro();
// Desloco o Sonic
this.x += this.velocidade;
}
else if (this.teclado.pressionada(SETA_ESQUERDA)) {
if (! this.andando || this.direcao != SONIC_ESQUERDA) {
this.sheet.linha = 2; // Atenção, aqui será 2!
this.sheet.coluna = 0;
}
this.andando = true;
this.direcao = SONIC_ESQUERDA;
this.sheet.proximoQuadro();
this.x -= this.velocidade; // E aqui é sinal de menos!
}
else {
if (this.direcao == SONIC_DIREITA)
this.sheet.coluna = 0;
else if (this.direcao == SONIC_ESQUERDA)
this.sheet.coluna = 1;
this.sheet.linha = 0;
// Não chamo proximoQuadro!
this.andando = false;
}
},
desenhar: function() {
this.sheet.desenhar(this.x, this.y);
}
}
----------------------------------------------------------------------------------------------------------
Spritesheet.js
function Spritesheet(context, imagem, linhas, colunas) {
this.context = context;
this.imagem = imagem;
this.numLinhas = linhas;
this.numColunas = colunas;
this.intervalo = 0;
this.linha = 0;
this.coluna = 0;
}
Spritesheet.prototype = {
proximoQuadro: function() {
var agora = new Date().getTime();
// Se ainda não tem último tempo medido
if (! this.ultimoTempo) this.ultimoTempo = agora;
// Já é hora de mudar de coluna?
if (agora - this.ultimoTempo < this.intervalo) return;
if (this.coluna < this.numColunas - 1)
this.coluna++;
else
this.coluna = 0;
// Guardar hora da última mudança
this.ultimoTempo = agora;
},
desenhar: function(x, y) {
var largura = this.imagem.width / this.numColunas;
var altura = this.imagem.height / this.numLinhas;
this.context.drawImage(
this.imagem,
largura * this.coluna,
altura * this.linha,
largura,
altura,
x,
y,
largura,
altura
);
}
}
----------------------------------------------------------------------------------------------------
animacao.js
function Animacao(context) {
this.context = context;
this.sprites = [];
this.ligado = false;
}
Animacao.prototype = {
novoSprite: function(sprite) {
this.sprites.push(sprite);
},
ligar: function() {
this.ligado = true;
this.proximoFrame();
},
desligar: function() {
this.ligado = false;
},
proximoFrame: function() {
// Posso continuar?
if ( ! this.ligado ) return;
// A cada ciclo, limpamos a tela ou desenhamos um fundo
this.limparTela();
// Atualizamos o estado dos sprites
for (var i in this.sprites)
this.sprites[i].atualizar();
// Desenhamos os sprites
for (var i in this.sprites)
this.sprites[i].desenhar();
// Chamamos o próximo ciclo
var animacao = this;
requestAnimationFrame(function() {
animacao.proximoFrame();
});
},
limparTela: function() {
var ctx = this.context;
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
}
}
---------------------------------------------------------------------------------------------
teclado.js
// Códigos de teclas - aqui vão todos os que forem necessários
var SETA_ESQUERDA = 37;
var SETA_DIREITA = 39;
var ESPACO = 32;
function Teclado(elemento) {
this.elemento = elemento;
// Array de teclas pressionadas
this.pressionadas = [];
// Array de teclas disparadas
this.disparadas = [];
// Funções de disparo registradas
this.funcoesDisparo = [];
var teclado = this;
elemento.addEventListener('keydown', function(evento) {
var tecla = evento.keyCode; // Tornando mais legível ;)
teclado.pressionadas[tecla] = true;
// Disparar somente se for o primeiro keydown da tecla
if (teclado.funcoesDisparo[tecla] && !teclado.disparadas[tecla]) {
teclado.disparadas[tecla] = true;
teclado.funcoesDisparo[tecla] () ;
}
});
elemento.addEventListener('keyup', function(evento) {
teclado.pressionadas[evento.keyCode] = false;
teclado.disparadas[evento.keyCode] = false;
});
}
Teclado.prototype = {
pressionada: function(tecla) {
return this.pressionadas[tecla];
},
disparou: function(tecla, callback) {
this.funcoesDisparo[tecla] = callback;
}
}
Nenhum comentário:
Postar um comentário