Up to date

This page is up to date for Godot 4.3. If you still find outdated information, please open an issue.

Movimiento en 2D

Introducción

Todos los principiantes han pasado por esto: "¿Cómo muevo mi personaje?" Dependiendo del estilo de juego que estés haciendo, puedes tener requerimientos especiales pero, en general, el movimiento en la mayoría de los juegos 2D está basado en una pequeña cantidad de estilos.

Utilizaremos CharacterBody2D para estos ejemplos, pero los principios aplican también a otros tipos de nodos (Area2D, RigidBody2D).

Organización

Cada ejemplo mostrado debajo, usa la misma configuración de escena. Comienza con un CharacterBody2D con dos hijos: Sprite2D y CollisionShape2D. Puedes utilizar el ícono de Godot ("icon.png") o cualquier otra imagen que tengas para la textura del Sprite2D.

Abre Projecto -> Ajustes del Proyecto y selecciona la pestaña Mapa de entradas. Agrega las siguientes acciones (ver InputEvent para más detalles):

../../_images/movement_inputs.webp

Movimiento en 8 sentidos

En este escenario, quieres que el usuario pueda presionar las cuatro teclas direccionales (arriba/izquierda/abajo/derecha o W/A/S/D) y se mueva en la dirección indicada. El nombre "movimiento en 8 sentidos" (o 8-way movement en inglés) viene del hecho de que el jugador se puede mover diagonalmente al presionar dos teclas al mismo tiempo.

../../_images/movement_8way.gif

Añade un script al character body y agrega el siguiente código:

extends CharacterBody2D

@export var speed = 400

func get_input():
    var input_direction = Input.get_vector("left", "right", "up", "down")
    velocity = input_direction * speed

func _physics_process(delta):
    get_input()
    move_and_slide()

En la función get_input(), usamos Input get_vector() para verificar los cuatro eventos clave y la suma devuelve un vector de dirección.

Luego podemos establecer nuestra velocidad multiplicando este vector de dirección, que tiene una longitud de 1, por nuestra velocidad deseada.

Truco

Si nunca antes has usado cálculo vectorial (operaciones matemáticas entre vectores) o necesitas un recordatorio, puedes ver la explicación del uso en Godot en Matemáticas vectoriales.

Nota

Si el código anterior no hace nada cuando presionas las teclas, vuelve a revisar que has configurado las acciones de entrada correctamente como se describió en la parte Organización de este tutorial.

Rotación + movimiento

Este tipo de movimientos es a veces llamado "estilo Asteroids" porque recuerda al funcionamiento del juego clásico de ese nombre. Presionando izquierda/derecha rota el personaje, mientras que arriba/abajo lo mueve hacia adelante y hacia atrás acorde a la dirección a la que apunta.

../../_images/movement_rotate1.gif
extends CharacterBody2D

@export var speed = 400
@export var rotation_speed = 1.5

var rotation_direction = 0

func get_input():
    rotation_direction = Input.get_axis("left", "right")
    velocity = transform.x * Input.get_axis("down", "up") * speed

func _physics_process(delta):
    get_input()
    rotation += rotation_direction * rotation_speed * delta
    move_and_slide()

Aquí hemos agregado dos variables nuevas para seguir la dirección de rotación y velocidad. La rotación es aplicada directamente a la propiedad rotation del cuerpo.

Para establecer la velocidad, usamos transform.x del cuerpo, que es un vector que apunta en la dirección "hacia adelante" del cuerpo, y lo multiplicamos por la velocidad.

Rotación + movimiento (ratón)

Este estilo de movimiento es una variante del anterior. Ahora, la dirección es indicada por la posición del ratón en lugar del teclado. El personaje siempre "mirará hacia" el puntero del ratón. El movimiento hacia adelante y hacia atras se mantiene igual.

../../_images/movement_rotate2.gif
extends CharacterBody2D

@export var speed = 400

func get_input():
    look_at(get_global_mouse_position())
    velocity = transform.x * Input.get_axis("down", "up") * speed

func _physics_process(delta):
    get_input()
    move_and_slide()

Aquí estamos usando el método look_at() de Node2D para que el personaje mire en la dirección en la que esté ratón. Sin esta funcionalidad, podrías obtener el mismo efecto asignando el ángulo de la siguiente forma:

rotation = get_global_mouse_position().angle_to_point(position)

Clic y mover

Este último ejemplo utiliza sólo el ratón para controlar el personaje. Haciendo clic en la pantalla ocasiona que el jugador se mueva a la posición indicada.

../../_images/movement_click.gif
extends CharacterBody2D

@export var speed = 400

var target = position

func _input(event):
    # Use is_action_pressed to only accept single taps as input instead of mouse drags.
    if event.is_action_pressed(&"click"):
        target = get_global_mouse_position()

func _physics_process(delta):
    velocity = position.direction_to(target) * speed
    # look_at(target)
    if position.distance_to(target) > 10:
        move_and_slide()

Nota la comprobación distance_to() que se hace antes del movimiento. Sin esto, el cuerpo podría "temblar" al llegar al destino, ya que el movimiento puede pasarse un poco e intentará moverse hacia atrás, pasándose de largo nuevamente y repitiendo el proceso.

Quitando los comentarios en la línea que dice look_at() hará también que el cuerpo apunte a la dirección del movimiento.

Truco

Esta técnica también puede utilizarse como base para un personaje "persecutorio". La posición del objetivo puede ser la de cualquier objeto al que quieras moverte.

Sumario

Estos ejemplos pueden ser útiles como punto de partida para tus propios proyectos. Siéntete libre de usarlos y experimentar con ellos para ver lo que puedes hacer.

Puede descargar este proyecto de muestra aquí: 2d_movement_starter.zip