Movimiento en videojuegos

En este artículo vamos a explicar los diferentes tipos de movimiento en videojuegos con HTML5 y Canvas en juegos 2D. El movimiento en los videojuegos es una parte esencial que afecta tanto la jugabilidad como la experiencia del jugador.

A través del teclado, las teclas (CURSOR o WASD) suelen utilizarse para mover al personaje hacia adelante, atrás, izquierda y derecha en los videojuegos. También existen movimientos como correr, saltar, agacharse, etc. que pueden variar dependiendo del diseño del juego y de cómo se implementen los controles.

En este artículo nos centraremos únicamente en el movimiento en videojuegos que puede realizar nuestro personaje (adelante, atrás, izquierda, derecha). Dejando de lado otros movimientos y acciones adicionales como atacar, interactuar, habilidades especiales, etc. para otros artículos.

Tipos de movimiento en videojuegos

Lo primero que debemos tener en cuenta al implementar movimiento en videojuegos de tipo 2D es la pantalla y el eje de coordenadas (x, y). Estas coordenadas empiezan en la esquina superior izquierda (0, 0) y terminan en la esquina inferior derecha (width, height).

Para mover nuestro personaje a lo largo de estos dos ejes simplemente modificamos su posición (x, y) en base a un desplazamiento que llamaremos velocidad. La manera de hacer estos cambios en la posición (x, y) es lo que va a dar mayor o menor realismo al movimiento.

Hay varios tipos de movimiento en videojuegos que podemos implementar:

  • Movimiento vertical / horizontal: Consiste en aplicar la velocidad directamente a cada uno de los ejes (x, y) según las acciones del usuario.
  • Movimiento en 360 grados: Es un movimiento calculado a partir de un ángulo de 360 grados aplicando su seno y coseno a la velocidad. Este movimiento permite hacer giros y rotaciones naturales o realistas de 360 grados.
  • Aceleración / desaceleración: Es un factor que se aplica a la velocidad del movimiento, creando aceleración y desaceleración y produciendo un movimiento más realista.

Dependiendo de la naturaleza de nuestro videojuego, optaremos por un movimiento u otro para conseguir más realismo. Veamos como implementar cada uno de estos movimientos en nuestros videojuegos.

NOTA: En los siguientes códigos de ejemplo utilizo el Controlador de teclado JavaScript descrito en un artículo anterior.

Movimiento vertical / horizontal

Este es el movimiento más sencillo, simplemente se suma o resta la velocidad del personaje a su posición. Es útil para juegos muy básicos pero le falta realismo. Una manera de implementarlo sería la siguiente:

if (keyboard.key('ArrowUp')) player.y -= player.speed;
if (keyboard.key('ArrowDown')) player.y += player.speed;
if (keyboard.key('ArrowLeft')) player.x -= player.speed;
if (keyboard.key('ArrowRight')) player.x += player.speed;

Partimos de la base que tenemos un Objeto player con todos los datos de su posición, velocidad, etc. y que tenemos instanciada nuestra Clase keyboardClass, esta sería la forma de mover el personaje. Cada vez que pasemos por este código y cualquiera de las teclas del CURSOR esté pulsada se aplicará la velocidad.

Recuerda que la Clase keyboardClass detecta teclas simultáneamente pulsadas, por lo que se puede ejecutar un movimiento en diagonal, combinando varias teclas.

Movimiento de 360 grados

Este es un movimiento más complejo que requiere de unos cálculos más sofisticados que en el movimiento anterior. Además, hay que tener en cuenta que debido a cómo crecen los ejes (x, y) debemos imaginarnos los ángulos de 360 grados en nuestro lienzo <canvas> de la siguiente manera:

Movimiento 360 grados

El movimiento de 360 grados tiene unas cuantas particularidades a tener en cuenta:

  • El movimiento y dirección en ángulos del personaje deben concidir. Esto obliga a dibujar el personaje en reposo «mirando» hacia la derecha de manera que coincida con el ángulo 0.
  • Los ángulos nos proporcionan una mejor «visualización mental» de hacia donde mira nuestro personaje, pero las operaciones matemáticas se calculan en Radianes.

Dicho todo esto la implementación del movimiento de 360 grados en nuestros videojuegos se haría de la siguiente manera:

if (keyboard.key('ArrowUp')) player.speed = 5;
if (keyboard.key('ArrowDown')) player.speed = 0;
if (keyboard.key('ArrowLeft')) player.angle -= 5;
if (keyboard.key('ArrowRight')) player.angle += 5;
player.radians = player.angle * (Math.PI/180);
player.x += Math.cos(player.radians) * player.speed;
player.y += Math.sin(player.radians) * player.speed;

Movimiento de 360 grados en videojuegos

Partimos de la misma base que en el movimiento vertical /horizontal, tenemos un Objeto player con todos los datos de su posición, velocidad, angulo, radianes, etc. y también tenemos instanciada nuestra Clase keyboardClass. El movimiento de 360 grados en videojuegos tiene las siguientes características adicionales:

  • Las teclas del CURSOR arriba y abajo generalmente se usan para acelerar y frenar. En este caso utilizamos la variable de velocidad (speed) para controlar si hay movimiento o se ha frenado.
  • Las teclas del CURSOR izquierda y derecha se usan para girar el personaje a izquierda y derecha. En este caso utilizamos la variable (angle) para aumentar o disminuir su rotación a izquierda o derecha.
  • Para calcular el movimiento primero pasamos el ángulo a radianes con una simple fórmula matemática.
  • Calculamos el desplazamiento de cada eje (x, y) multiplicando la velocidad por el seno y coseno del ángulo de dirección obtenido en radianes, respectivamente.

Esta es la forma de obtener un movimiento de giro fluido y realista de 360 grados en nuestros videojuegos. Este movimiento suele emplearse junto a otra técnica de dibujo: la rotación, que explicaremos en otros artículos.

Observa que al aplicar una velocidad igual a cero no hay movimiento. Esto facilta los cálculos pero también hace que los cambios de velocidad sean bruscos y haga falta implementar el último tipo de movmiento en videojuegos: la aceleración y desaceleración.

Movimiento con aceleración y desaceleración

Si consideramos que las teclas del CURSOR adelante y atrás suelen usarse para acelerar y frenar, podemos añadir un componente de aceleración y fricción. Este componente se puede aplicar de diferentes formas para mejorar la sensación de realismo y control del jugador:

  • Aceleración gradual: Cuando el jugador presiona la tecla de movimiento, la velocidad del personaje aumenta gradualmente hasta alcanzar su velocidad máxima.
  • Desaceleración gradual: Cuando el jugador deja de presionar la tecla de movimiento, la velocidad del personaje disminuye gradualmente hasta detenerse por completo.
  • Aceleración/desaceleración basada en la física: Algunos juegos implementan aceleración y desaceleración basadas en principios físicos, como la aplicación de fuerzas y fricción. Esto puede combinarse con otras físicas como las masa, gravedad, etc.

En este artículo vamos a aplicar una aceleración al avanzar, desaceleración al frenar y fricción al soltar las teclas. Pero en vez de aplicarlo al movimiento de 360 grados, lo vamos a aplicar al movimiento vertical / horizontal. De esta forma debemos aplicar la aceleración y fricción en los dos ejes (x, y) y controlar las 4 teclas del CURSOR. Un concepto ligeramente más complicado que simplemente acelerar y frenar.

Código para acelerar y desacelerar con fricción

Imaginemos que tenemos el siguiente Objeto para dibujar un círculo relleno que podemos mover con el teclado:

player = {
  speedX: 0,  
  speedY: 0,  
  mSpeed: 5,              
  radius: 15,   
  color: "green",          
  friction: 0.02,   
  aceleration: 0.2,
  x: canvas.width/2 - 15,
  y: canvas.height/2 - 15,              
}; 

Para crear el movimiento con aceleración, desaceleración y fricción utilizamos unas cuantas variables de la siguiente manera para crear el movimiento en el videojuego:

// Variables del movimiento
let moveX = 0;
let moveY = 0;

// Detecta teclado y establecer dirección
if (keyboard.key('ArrowUp')) moveY = -player.aceleration;
if (keyboard.key('ArrowDown')) moveY = player.aceleration;
if (keyboard.key('ArrowLeft')) moveX = -player.aceleration;
if (keyboard.key('ArrowRight')) moveX = player.aceleration;

// Aplica fricción o aceleración dependiendo de la entrada de teclado
if (moveY == 0) player.speedY = Math.abs(player.speedY) < player.friction ? 0 : player.speedY -    Math.sign(player.speedY) * player.friction;
else player.speedY += moveY;
if (moveX == 0) player.speedX = Math.abs(player.speedX) < player.friction ? 0 : player.speedX - Math.sign(player.speedX) * player.friction;
else player.speedX += moveX;  

// Limita velocidad al valor máximo
player.speedY = Math.min(Math.max(player.speedY, -player.mSpeed), player.mSpeed);
player.speedX = Math.min(Math.max(player.speedX, -player.mSpeed), player.mSpeed);      

// Actualiza posición del jugador
player.y += player.speedY;
player.x += player.speedX; 

Movimiento con aceleración, desaceleración y fricción

Como vemos, el código utilizado es un poco complejo y su explicación es la siguiente:

  • Variables del movimiento: Se inicializan las variables (moveX, moveY) en 0 para conocer la dirección del movimiento del jugador.
  • Detectar teclado y establecer dirección: Se verifican las teclas presionadas por el usuario para determinar la dirección del movimiento del jugador. Se establecen las variables (moveX, moveY) en el valor correspondiente a la aceleración del jugador (player.aceleration).
  • Aplicar fricción si no hay entrada de teclado: Si no hay entrada de teclado, se reduce la velocidad aplicando fricción en dirección opuesta al movimiento actual. Si la velocidad es menor a la fricción se establece en 0 para detener el movimiento.
  • Aplicar aceleración si hay entrada de teclado: Se agregan las direcciones del movimiento (moveX, moveY) a las velocidades actuales del jugador (player.speedX, player.speedY). Esto mueve el jugador en la dirección determinada por las teclas presionadas. Incrementando o drecrementando la velocidad teniendo en cuenta la aceleración y la fricción.
  • Limitar la velocidad al valor de mSpeed: Se asegura que la velocidad del jugador no exceda la velocidad máxima permitida establecida en (mSpeed). Se utiliza Math.min y Math.max para establecer los límites de velocidad tanto en el eje X como en el eje Y.
  • Actualizar la posición del jugador: Finalmente, se actualiza la posición del jugador agregando las velocidades (player.speedX, player.speedY) a las coordenadas (x, y) del jugador respectivamente. Esto hace que el jugador se mueva en la pantalla según las velocidades calculadas.

En resumen, este código controla el movimiento del jugador utilizando aceleración, desaceleración y fricción, limitando la velocidad para lograr un movimiento suave y controlable en el juego. Si cambiamos los valores de la aceleración, fricción y velocidad máxima (aceleration, friction, mSpeed) podemos obtendremos diferentes tipos de movimiento, de más suave a más brusco.

Resumen de movimiento en videojuegos

El movimiento en videojuegos parece una cosa sencilla pero se puede ir complicando. Cuanto más realista queremos el movimiento más debemos ceñirnos a la realidad. Estamos acostumbrados a la física de la vida real y los videojuegos deben simularla. Un videojuego no necesita crear físicas idénticas a la vida real, que costaría muchos cálculos, pero sí debe crear «simulaciones» parecidas.

En este aspecto las físicas «simuladas» explicadas en este artículo cumplen con las espectativas y sirven como introducción al movimiento en videojuegos 2D. Puedes hacer tus propios experimentos y si quieres saber más sobre el movimiento en videojuegos 2D, lo explico más ámpliamente en mis libros sobre videojuegos.

¡ Espero que este artículo sea de vuestro interés !

Deja un comentario