[JS] Problema ao movimentar o jogador pelo <canvas>
Boa tarde, galera!
Estou com problemas ao executar este programa, o player nasce fora do canvas, os botoes de movimento parecem estar bugados, e quando consigo trazer o player para dentro do canvas ele deixa rastros.
Código:
const canvas = document.getElementById('canvas')
const ctx = canvas.getContext('2d')
var x = canvas.style.width/2 //começa no meio do x (player)
var y = canvas.style.height/2 //começa no meio do y (player)
//objeto player com propriedades do quadrado
var player = {
color: 'black',
altura: '10',
largura: '10',
position: {
coordx: x,
coordy: y
},
mover: {
cima: () => this.position.coordy = y++,
baixo: () => this.position.coordy = y--,
direita: () => this.position.coordx = x++,
esquerda: () => this.position.coordx = x--
},
}
//desestruturação do objeto player
var {color, altura, largura, position, mover} = player
//le a tecla digitada
document.addEventListener('keydown', event => {
switch(event.keyCode){
case 37: //esquerda
mover.esquerda()
break;
case 39: //direita
mover.direita()
break;
case 38: //cima
mover.cima()
break;
case 40: //baixo
mover.baixo()
break;
}
})
//desenha o player na tela
function draw(){
ctx.fillRect(position.coordx, position.coordx, largura, altura)
ctx.fillStyle = color
ctx.clearRect(position.coordx, position.coordy, largura, altura)
requestAnimationFrame(draw) //looping do programa
}
draw() //inicio do programa
HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
#canvas{
height: 400;
width: 400;
background-color: aquamarine;
}
</style>
</head>
<body>
<canvas id="canvas"></canvas>
<script>
//script esta em cima
</script>
</body>
</html>
keyCode
está deprecated e não é mais recomendado. Em vez disso, uma alternativa é usar a propriedade key
.
Pra que criar o objeto player
se depois você vai desestruturá-lo? Se for usá-lo somente para isso, compensa mais criar as variáveis diretamente.
Além disso, sugiro usar os eventos keydown
e keyup
em conjunto: o primeiro detecta se a tecla foi pressionada, e o segundo detecta se a tecla foi solta. Assim você pode detectar quando o usuário fica segurando a tecla, por exemplo (aí o personagem continua andando, até que a tecla seja solta). E vc também pode mudar duas direções ao mesmo tempo (por exemplo, se eu segurar as setas para cima e direita ao mesmo tempo, ele deveria andar na diagonal).
Um exemplo bem simples pode ser encontrado aqui. Adaptando para o seu caso, ficou assim:
// detecta se cada uma das teclas está pressionada
let up = false, down = false, left = false, right = false;
// A posição do personagem na tela
let pos = { x: 0, y: 0 };
// Velocidade de deslocamento do personagem (pode aumentar para ele andar mais posições de uma vez)
let velocidade = 1;
//Quando pressionada uma tecla específica sinaliza o seu estado como pressionado
document.addEventListener("keydown", (event) => {
if (event.key == "ArrowUp") up = true;
if (event.key == "ArrowDown") down = true;
if (event.key == "ArrowLeft") left = true;
if (event.key == "ArrowRight") right = true;
});
//Quando solta um tecla específica sinaliza o seu estado como não pressionado
document.addEventListener("keyup", (event) => {
if (event.key == "ArrowUp") up = false;
if (event.key == "ArrowDown") down = false;
if (event.key == "ArrowLeft") left = false;
if (event.key == "ArrowRight") right = false;
});
var canvas, ctx;
const color = 'black', altura = 10, largura = 10;
// Ao carregar a página...
window.addEventListener("load", () => {
canvas = document.getElementById('canvas');
ctx = canvas.getContext('2d');
pos.x = canvas.width / 2;
pos.y = canvas.height / 2;
requestAnimationFrame(draw); //inicio do programa
});
// desenha o player na tela
function draw() {
// Para cada uma das teclas do direcional verifica se está pressionada, e aplica um deslocamento
if (up) pos.y -= velocidade;
if (down) pos.y += velocidade;
if (left) pos.x -= velocidade;
if (right) pos.x += velocidade;
ctx.clearRect(0, 0, canvas.width, canvas.height); // limpa o canvas
ctx.fillRect(pos.x, pos.y, largura, altura); // desenha
ctx.fillStyle = color;
requestAnimationFrame(draw); // looping do programa
}
Vê se assim resolve... P.S.: Dessa forma ele anda na diagonal
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
#canvas{
height: 400;
width: 400;
background-color: aquamarine;
}
.flex {
-webkit-flex: 1;
flex: 1;
}
</style>
</head>
<body>
<canvas id="canvas"></canvas>
<div class="flex">
<pre id="console-log"></pre>
</div>
<script>
var gameReady = true;
let consoleLog = document.getElementById('console-log')
const canvas = document.getElementById('canvas')
const ctx = canvas.getContext('2d')
var x = canvas.width/2 //começa no meio do x (player)
var y = canvas.height/2 //começa no meio do y (player)
var vel = 1
function messageLog(message) {
consoleLog.innerHTML += `${message}<br>`;
}
var Keys = {
up: false,
down: false,
left: false,
right: false
};
//objeto player com propriedades do quadrado
var player = {
color: 'black',
altura: '10',
largura: '10',
position: {
coordx: x,
coordy: y
}
}
//desestruturação do objeto player
var {color, altura, largura, position, mover} = player
//le a tecla digitada
window.onkeydown = function(e){
//messageLog(`Key "${event.key}" pressed [event: keypress]`);
var kc = e.keyCode;
e.preventDefault();
if(kc === 37) Keys.left = true;
if(kc === 38) Keys.up = true;
if(kc === 39) Keys.right = true;
if(kc === 40) Keys.down = true;
}
window.onkeyup = function(e){
var kc = e.keyCode;
e.preventDefault();
if(kc === 37) Keys.left = false;
if(kc === 38) Keys.up = false;
if(kc === 39) Keys.right = false;
if(kc === 40) Keys.down = false;
}
function move() {
if(Keys.up) {
player.position.coordy -= vel;
}
if(Keys.down) {
player.position.coordy += vel;
}
if(Keys.left) {
player.position.coordx -= vel;
}
if(Keys.right) {
player.position.coordx += vel;
}
}
//desenha o player na tela
function draw() {
move()
ctx.clearRect(0, 0, canvas.width, canvas.height)
ctx.fillRect(position.coordx, position.coordy, largura, altura)
ctx.fillStyle = color
requestAnimationFrame(draw) //looping do programa
}
//inicio do programa
draw();
</script>
</body>
</html>