How do I get axis input?

Godot: Domina el Input de Eje como un Profesional

16/10/2022

Valoración: 4.95 (9192 votos)

En el corazón de cualquier juego interactivo se encuentra un sistema de entrada robusto y receptivo. Sin él, el jugador no puede conectar con el mundo que has creado. En Godot Engine, la gestión de todas las interacciones del jugador, ya sea desde un teclado, un ratón o un gamepad, se centraliza en un poderoso nodo global: el singleton Input. Este artículo es una inmersión profunda en una de las tareas más comunes y cruciales: la captura de entradas de eje. Aprenderás no solo a detectar si una tecla está presionada, sino a interpretar la intensidad y la dirección del movimiento, una habilidad esencial para crear controles de personaje fluidos y profesionales.

How do I get axis input?
Get axis input by specifying two actions, one negative and one positive. This is a shorthand for writing Input.get_action_strength("positive_action") - Input.get_action_strength("negative_action"). Returns an Array containing the device IDs of all currently connected joypads. Returns the currently assigned cursor shape (see CursorShape).
Índice de Contenido

Entendiendo el Concepto de Eje y Acciones

Antes de escribir una sola línea de código, es fundamental comprender dos conceptos: qué es una entrada de "eje" y cómo funciona el sistema de "acciones" de Godot.

Una entrada de eje no es un simple estado de "encendido/apagado" como el clic de un botón. En su lugar, representa un valor a lo largo de un espectro, típicamente entre -1.0 y 1.0. Piensa en el stick analógico de un gamepad: cuando está en reposo, su valor es 0. Si lo empujas completamente hacia la derecha, su valor en el eje horizontal es 1.0; completamente a la izquierda, es -1.0. Cualquier posición intermedia se traduce en un valor fraccionario. Este tipo de entrada es perfecto para movimientos que requieren sutileza y control de velocidad.

Godot abstrae los dispositivos físicos (teclas, botones de gamepad, etc.) a través de un sistema llamado Input Map. En lugar de codificar directamente "si se presiona la tecla W", defines una acción como "mover_arriba" y luego asocias la tecla W, la flecha hacia arriba del teclado y el stick izquierdo hacia arriba de un gamepad a esa misma acción. Esto hace que tu código sea increíblemente flexible y fácil de configurar para el usuario final.

Configurando el Input Map

Para empezar, debemos definir nuestras acciones. Sigue estos pasos:

  1. Ve al menú superior y selecciona Proyecto > Ajustes del Proyecto...
  2. Navega a la pestaña Mapa de Entrada.
  3. En la parte superior, verás un campo para añadir una nueva acción. Escribe el nombre de tu primera acción, por ejemplo, move_right, y haz clic en "Añadir".
  4. Repite el proceso para las otras acciones necesarias: move_left, move_up, y move_down.
  5. Una vez creadas las acciones, haz clic en el icono "+" a la derecha de cada una para añadirle un evento. Selecciona "Evento de Tecla" para el teclado.
  6. Presiona la tecla correspondiente (por ejemplo, la tecla 'D' para move_right) y haz clic en "Aceptar".
  7. Asigna las teclas que prefieras a cada acción. Una configuración común es usar WASD y las teclas de flecha para cada una de las cuatro direcciones.

Con estas acciones configuradas, nuestro proyecto ya no depende de teclas específicas, sino de conceptos abstractos de movimiento que podemos consultar en nuestro código.

El Método `get_axis()`: La Vía Directa

El método más sencillo para obtener una entrada de eje es Input.get_axis(). Esta función toma dos argumentos: el nombre de la acción negativa y el nombre de la acción positiva.

get_axis(negative_action: StringName, positive_action: StringName) -> float

Devuelve un valor flotante entre -1.0 y 1.0. Si se presiona la acción positiva, devuelve 1.0. Si se presiona la negativa, -1.0. Si no se presiona ninguna o se presionan ambas, devuelve 0.0. Es, en esencia, un atajo para la operación Input.get_action_strength("accion_positiva") - Input.get_action_strength("accion_negativa").

Ejemplo Práctico con `get_axis()`

Imaginemos que tenemos un nodo CharacterBody2D. En su script, dentro de la función _physics_process(delta), podemos obtener el input del jugador de la siguiente manera:

extends CharacterBody2D const SPEED = 300.0 func _physics_process(delta): var horizontal_axis = Input.get_axis("move_left", "move_right") var vertical_axis = Input.get_axis("move_up", "move_down") # Creamos un vector de dirección a partir de los ejes var direction = Vector2(horizontal_axis, vertical_axis) # Aplicamos la velocidad velocity = direction * SPEED move_and_slide() 

Este código funciona, pero tiene un problema sutil: el movimiento diagonal es más rápido. Esto ocurre porque si, por ejemplo, direction es Vector2(1, 1), la magnitud de ese vector es √2 (aproximadamente 1.414), no 1. Para solucionar esto, necesitaríamos normalizar el vector: velocity = direction.normalized() * SPEED. Sin embargo, Godot nos ofrece una solución aún mejor y más integrada.

El Método `get_vector()`: La Solución Definitiva para Movimiento

Para el movimiento en 2D, el método get_vector() es casi siempre la opción superior. Combina cuatro acciones para crear un vector de dirección Vector2, y lo más importante, ¡ya viene normalizado!

get_vector(negative_x: StringName, positive_x: StringName, negative_y: StringName, positive_y: StringName) -> Vector2

Esta función se encarga de todo el trabajo pesado. Calcula la dirección, limita la magnitud del vector a 1.0 (evitando el problema de la velocidad diagonal) y aplica una zona muerta (deadzone) circular, lo cual es ideal para los sticks analógicos de los gamepads.

Ejemplo Práctico con `get_vector()`

Refactoricemos nuestro ejemplo anterior usando este método más potente:

extends CharacterBody2D const SPEED = 300.0 func _physics_process(delta): # Una sola línea para obtener un vector de dirección normalizado var direction = Input.get_vector("move_left", "move_right", "move_up", "move_down") # Aplicamos la velocidad directamente velocity = direction * SPEED move_and_slide() 

Como puedes ver, el código no solo es más limpio y conciso, sino también más correcto. El movimiento del personaje será consistente en todas las direcciones sin necesidad de cálculos adicionales por nuestra parte.

Tabla Comparativa: `get_axis()` vs. `get_vector()`

Para resumir las diferencias y ayudarte a decidir cuál usar en cada situación, aquí tienes una tabla comparativa:

CaracterísticaInput.get_axis()Input.get_vector()
Valor de RetornoUn solo valor float (-1.0 a 1.0) para un eje.Un Vector2 que combina dos ejes.
NormalizaciónNo. Requiere normalización manual si se combinan dos ejes.Sí. El vector resultante tiene una longitud máxima de 1.0.
Zona Muerta (Deadzone)Aplicada por acción individualmente.Aplica una zona muerta circular, ideal para joysticks.
Caso de Uso PrincipalEntradas unidimensionales, como el acelerador en un juego de carreras o el zoom de una cámara.Movimiento de personajes en 2D (top-down, plataformas), control de cámaras orbitales.
ComplejidadMuy simple para un solo eje, requiere más código para dos.Extremadamente simple y directo para movimiento en 2D.

Preguntas Frecuentes (FAQ)

¿Qué es una "zona muerta" o "deadzone"?

Es un pequeño umbral alrededor del punto central (0,0) de un stick analógico. Cualquier movimiento del stick dentro de esta zona se ignora. Esto es crucial para evitar el "drift" o movimiento fantasma, que ocurre cuando un control ligeramente desgastado no regresa exactamente a la posición cero, haciendo que el personaje se mueva lentamente por sí solo.

¿Debo poner mi código de input en `_process(delta)` o `_physics_process(delta)`?

La regla general es: si el input va a afectar a la física (movimiento de un CharacterBody o RigidBody), colócalo en _physics_process(delta). Esta función se ejecuta a una velocidad de fotogramas fija, lo que garantiza que la simulación física sea estable y consistente. Para inputs que no afectan a la física, como la navegación por menús o acciones que no necesitan sincronización con la física, _process(delta) es adecuado.

¿Puedo leer la entrada de un joystick directamente sin usar el Input Map?

Sí. El singleton Input proporciona métodos como get_joy_axis(device_id, axis_enum) para leer el valor crudo de un eje de un gamepad específico. Sin embargo, esto es menos flexible. Usar el Input Map te permite soportar diferentes tipos de controladores y remapeo de teclas sin cambiar una sola línea de tu código de juego. Generalmente, siempre es preferible usar el sistema de acciones.

¿Cómo funciona con los gatillos de un gamepad?

Los gatillos analógicos (como L2/R2 en un mando de PlayStation) también son ejes. Puedes mapearlos a una acción en el Input Map. Input.get_action_strength("acelerar") te devolverá un valor de 0.0 (sin presionar) a 1.0 (presionado a fondo), permitiéndote tener un control de aceleración variable.

Dominar el singleton Input es un paso fundamental en tu viaje como desarrollador en Godot. Al comprender y utilizar correctamente métodos como get_axis y, especialmente, get_vector, estarás equipado para crear controles de jugador que no solo funcionan, sino que se sienten geniales. ¡Ahora ve y dale a tus personajes el movimiento fluido y responsivo que se merecen!

Si quieres conocer otros artículos parecidos a Godot: Domina el Input de Eje como un Profesional puedes visitar la categoría Juegos.

Subir