Escuchando la entrada del jugador
Basándonos en la lección anterior Crear tu primer script, vamos a ver otra característica importante de cualquier juego: dar el control al jugador. Para añadir esto, necesitaremos modificar nuestro código en sprite_2d.gd.
Tienes dos herramientas principales para procesar la entrada del jugador en Godot:
Los callbacks de entrada incorporados, principalmente
_unhandled_input(). Al igual que_process(), es una función virtual incorporada que Godot llama cada vez que el jugador presiona una tecla. Es la herramienta que desea usar para reaccionar ante eventos que no suceden en cada cuadro, como presionar Espacio para saltar. Para obtener más información sobre los callbacks de entrada, véase Usar InputEvent.El singleton
Input. Un singleton es un objeto accesible globalmente. Godot proporciona acceso a varios scripts. Es la herramienta adecuada para verificar para las entradas en cada frame.
Vamos a usar el singleton Input aquí, ya que necesitamos saber si el jugador quiere girar o mover cada frame.
Para girar, debemos utilizar una nueva variable: direction. En nuestra función _process(), sustituye la línea rotation += angular_speed * delta por el código siguiente.
var direction = 0
if Input.is_action_pressed("ui_left"):
direction = -1
if Input.is_action_pressed("ui_right"):
direction = 1
rotation += angular_speed * direction * delta
var direction = 0;
if (Input.IsActionPressed("ui_left"))
{
direction = -1;
}
if (Input.IsActionPressed("ui_right"))
{
direction = 1;
}
Rotation += _angularSpeed * direction * (float)delta;
Nuestra variable local direction es un multiplicador que representa la dirección en la que el jugador quiere girar. Un valor de 0 significa que el jugador no está presionando la tecla de flecha izquierda o derecha. Un valor de 1 significa que el jugador quiere girar a la derecha, y -1 significa que quiere girar a la izquierda.
To produce these values, we introduce conditional statements and the use of Input.
A conditional statement starts with the if keyword in GDScript and ends with a colon. The
condition is specifically the expression between the keyword and the colon at
the end of the line.
Para verificar si se presionó una tecla en este frame, llamamos Input.is_action_pressed(). El método toma una cadena de texto que representa una acción de entrada y devuelve true si se presiona la acción, false de lo contrario.
Las dos acciones que usamos arriba, "ui_left" y "ui_right", están predefinidas en cada proyecto de Godot. Se activan respectivamente cuando el jugador presiona las flechas izquierda y derecha en el teclado o izquierda y derecha en el pad direccional de un gamepad.
Nota
You can see and edit input actions in your project by going to and clicking on the Input Map tab.
Finalmente, usamos la direction como un multiplicador cuando actualizamos la rotation del nodo: rotation += angular_speed * direction * delta.
Comentamos las líneas var velocity = Vector2.UP.rotated(rotation) * speed y position += velocity * delta de esta manera:
#var velocity = Vector2.UP.rotated(rotation) * speed
#position += velocity * delta
//var velocity = Vector2.Up.Rotated(Rotation) * _speed;
//Position += velocity * (float)delta;
Esto hará que se ignore el código que movía la posición del icono en forma circular sin la entrada del usuario del ejercicio anterior.
Si ejecutas la escena con este código, el icono debería rotar cuando presiona Izquierda y Derecha.
Moverse al presionar "arriba"
Para movernos solo al pulsar una tecla, necesitamos modificar el código que calcula la velocidad. Reemplace la línea que comienza con var velocity con el siguiente código.
var velocity = Vector2.ZERO
if Input.is_action_pressed("ui_up"):
velocity = Vector2.UP.rotated(rotation) * speed
var velocity = Vector2.Zero;
if (Input.IsActionPressed("ui_up"))
{
velocity = Vector2.Up.Rotated(Rotation) * _speed;
}
Inicializamos la velocity con un valor de Vector2.ZERO, otra constante incorporada del tipo Vector que representa un vector 2D de longitud 0.
Si el jugador presiona la acción "ui_up", actualizamos el valor de la velocidad, lo que hace que el sprite se mueva hacia adelante.
Script completo
Aquí está el archivo sprite_2d.gd completo como referencia.
extends Sprite2D
var speed = 400
var angular_speed = PI
func _process(delta):
var direction = 0
if Input.is_action_pressed("ui_left"):
direction = -1
if Input.is_action_pressed("ui_right"):
direction = 1
rotation += angular_speed * direction * delta
var velocity = Vector2.ZERO
if Input.is_action_pressed("ui_up"):
velocity = Vector2.UP.rotated(rotation) * speed
position += velocity * delta
using Godot;
public partial class MySprite2D : Sprite2D
{
private float _speed = 400;
private float _angularSpeed = Mathf.Pi;
public override void _Process(double delta)
{
var direction = 0;
if (Input.IsActionPressed("ui_left"))
{
direction = -1;
}
if (Input.IsActionPressed("ui_right"))
{
direction = 1;
}
Rotation += _angularSpeed * direction * (float)delta;
var velocity = Vector2.Zero;
if (Input.IsActionPressed("ui_up"))
{
velocity = Vector2.Up.Rotated(Rotation) * _speed;
}
Position += velocity * (float)delta;
}
}
Si ejecutas la escena, ahora debería poder rotar con las teclas de flecha izquierda y derecha y avanzar presionando Arriba.
Resumen
En resumen, cada script en Godot representa una clase y extiende una de las clases integradas del motor. Los tipos de nodos de los que heredan tus clases te dan acceso a propiedades como rotation y position en el caso de nuestro sprite. También heredas muchas funciones que no llegamos a utilizar en este ejemplo.
En GDScript, las variables que pones en la parte superior del archivo son las propiedades de su clase, también llamadas variables miembro. Además de las variables, puedes definir funciones que, en su mayor parte, serán los métodos de sus clases.
Godot proporciona varias funciones virtuales que puedes definir para conectar su clase con el motor. Estos incluyen _process(), para aplicar cambios al nodo en cada cuadro, y _unhandled_input(), para recibir eventos de entrada como pulsaciones de teclas y botones por parte de los usuarios. Hay bastantes más.
The Input singleton allows you to react to the player's input anywhere in
your code. In particular, you'll get to use it in the _process() loop.
En la siguiente lección Usar Señales, ampliaremos la relación entre scripts y nodos haciendo que nuestros nodos activen código en scripts.