Executando verificação de segurança...
1

[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>
Carregando publicação patrocinada...
2

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
}
1

Opaa! Muito obrigado!
Então, eu quis usar objeto e desestruturação para treinar, consegui fazer funcionar olhando seu código e vendo oq eu devia ter errado, da uma olhada:

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 = 10
        
        //objeto player com propriedades do quadrado
        var player = {
            color: 'black',
            altura: '10',
            largura: '10',
            position: {
                coordx: x,
                coordy: y
            },
            mover: {
                cima: () => this.position.coordy = this.position.coordy + vel,
                baixo: () => this.position.coordy = this.position.coordy - vel,
                direita: () => this.position.coordx = this.position.coordx + vel,
                esquerda: () => this.position.coordx = this.position.coordx - vel
            },
        }

        //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.baixo()
                    break;
                case 40: //baixo
                    mover.cima()
                    break;
            }
        }) 
        //desenha o player na tela
        function draw(){
                ctx.clearRect(0, 0, canvas.width, canvas.height)
                ctx.fillRect(position.coordx, position.coordy, largura, altura)
                ctx.fillStyle = color
                requestAnimationFrame(draw) //looping do programa
        }
        draw()  //inicio do programa

Eu não sei pq, mas quando uso o clearRect() no fim da função antes de chamar o requestAnimationFrame(), o player nao aparece na tela, deveria aparecer...

1

quando uso o clearRect() no fim da função antes de chamar o requestAnimationFrame(), o player nao aparece na tela,

Mas é claro. O clearRect está limpando o canvas. Veja na documentação que ele "zera" toda a área indicada. E como estamos usando 0, 0, canvas.width, canvas.height, então ele limpa toda a área do canvas.

Se vc chamar clearRect no final, ele vai limpar qualquer coisa que vc tiver desenhado antes. Por isso movi ele para o começo (primeiro limpa, depois desenha o que precisa).


Outra coisa, no meu código eu usei ponto-e-vírgula no final das linhas. Pode parecer "frescura", e sei que o JavaScript "aceita" o código sem ponto e vírgula e "funciona" (e tem até "cursinhos famosos" que dizem que não precisa usar), mas eu prefiro colocar, pois isso evita algumas situações bizarras que podem ocorrer se você não usá-los, como essa e essa (veja mais sobre isso aqui).

Quanto à desestruturação, sugiro treinar em um caso no qual faça sentido. Neste caso, da forma como foi feito, eu acho que não faz.

1

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>