CodeForge

Maquetación Web Dinámica / Canvas y videojuegos 2D

Interacción: teclado y mouse sobre canvas

Teoría22 min20 XP

Hasta ahora tus objetos obedecen a la física, pero no a ti. Esta lección conecta el control humano al canvas: mover una nave con las flechas, apuntar con el mouse, disparar con la barra. Y trae el patrón que separa un movimiento de juego fluido de uno a saltos — el error que casi todos cometen la primera vez.

El error clásico: mover dentro del evento

El patrón correcto: un objeto de teclas

teclado.js
const teclas = {};   // el "tablero de anotaciones": qué está presionado AHORA

// los listeners solo ANOTAN, no mueven nada
canvas.addEventListener("keydown", (e) => { teclas[e.key] = true; });
canvas.addEventListener("keyup",   (e) => { teclas[e.key] = false; });

function update() {
// el LOOP lee las anotaciones cada fotograma → movimiento fluido y continuo
if (teclas["ArrowLeft"])  x -= velocidad;
if (teclas["ArrowRight"]) x += velocidad;
if (teclas["ArrowUp"])    y -= velocidad;
if (teclas["ArrowDown"])  y += velocidad;
}

Este patrón regala dos cosas gratis: movimiento fluido (sin la demora de repetición del SO) y múltiples teclas a la vez (arriba + derecha = diagonal, porque son dos if independientes que se cumplen en el mismo fotograma). Los nombres de tecla vienen en e.key: "ArrowLeft", " " (la barra espaciadora es un espacio), "a", "Enter".

Muévela tú

Haz clic en el canvas (para darle foco) y mueve el cuadro con las flechas — prueba dos a la vez para la diagonal. El tabindex="0" en el <canvas> es lo que lo hace enfocable por teclado; sin él no recibiría los eventos. Y el e.preventDefault() sobre las flechas evita que la página haga scroll mientras juegas — cortesía obligatoria en juegos reales.

El mouse: coordenadas relativas al canvas

El evento de mouse te da la posición en la VENTANA; para saber dónde cayó DENTRO del canvas, restas la posición del canvas en pantalla con getBoundingClientRect():

mouse.js
canvas.addEventListener("mousemove", (e) => {
const rect = canvas.getBoundingClientRect();
const mx = e.clientX - rect.left;   // X dentro del canvas
const my = e.clientY - rect.top;    // Y dentro del canvas
// ...usa (mx, my): apuntar, arrastrar, dibujar
});

Saltarte la resta del rect es el bug clásico del mouse en canvas: el objetivo aparece desplazado, cada vez más lejos cuanto más abajo está el canvas en la página. Con la resta, (mx, my) es exacto — la base para apuntar un cañón, arrastrar una pieza o pintar.

Mueves tu personaje dentro del listener keydown. Al mantener una flecha, da un paso, se congela ~medio segundo y luego corre. ¿Por qué, y cómo se arregla?

Mini-reto

Dale "juice" a tu cuadrado: que deje de ser instantáneo y tenga INERCIA. En vez de x += vel directo, ten una velocidad vx que aumenta mientras presionas (vx += 0.5) y se frena sola cuando sueltas (vx *= 0.9 cada fotograma). El cuadrado ahora "patina" al arrancar y frenar, como sobre hielo — combinaste el input de hoy con la física de ayer. Ese detalle es la diferencia entre un control tosco y uno que se siente bien.

Qué sigue

Tu personaje es un cuadrado de color. La próxima lección le pone cara: sprites y spritesheets — cómo dibujar personajes desde una imagen y animarlos cuadro por cuadro (caminar, saltar) recortando la hoja de dibujos justo a tiempo.