Gestionar la entrada y el tiempo
Responda al jugador y al reloj
Gestionar la entrada y el tiempo es una lección gratuita de Learn Rust Coding en CoddyKit. Esta es la lección 3 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de Learn Rust Coding, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de Learn Rust Coding incluye 4 lecciones en total.
La entrada como recurso
El estado del teclado se encuentra en el recurso ButtonInput<KeyCode>, proporcionado por DefaultPlugins.
Solicítelo en modo de solo lectura con Res. Bevy lo actualiza en cada fotograma antes de ejecutar sus sistemas, por lo que siempre verá el estado actual.
fn read_keys(keys: Res<ButtonInput<KeyCode>>) {
if keys.pressed(KeyCode::Space) {
info!("space held");
}
}pressed frente a just_pressed
pressed es verdadero durante todos los fotogramas en los que se mantiene pulsada una tecla, por lo que resulta ideal para el movimiento continuo. just_pressed solo es verdadero en el fotograma en que se pulsa la tecla.
Utilice just_pressed para acciones discretas, como saltar o disparar, de modo que un solo toque dispare una vez.
fn jump(keys: Res<ButtonInput<KeyCode>>) {
if keys.just_pressed(KeyCode::ArrowUp) {
info!("jump!");
}
}Construcción de un vector de dirección
Combine varias teclas en una dirección de movimiento. Comience en cero y sume una unidad en cada eje por cada tecla pulsada.
Normalizar el resultado evita que el movimiento diagonal sea más rápido que el movimiento en línea recta.
fn direction(keys: Res<ButtonInput<KeyCode>>) -> Vec2 {
let mut d = Vec2::ZERO;
if keys.pressed(KeyCode::KeyW) { d.y += 1.0; }
if keys.pressed(KeyCode::KeyS) { d.y -= 1.0; }
if keys.pressed(KeyCode::KeyA) { d.x -= 1.0; }
if keys.pressed(KeyCode::KeyD) { d.x += 1.0; }
d.normalize_or_zero()
}El recurso Time
La frecuencia de fotogramas varía según el equipo, por lo que nunca debe mover algo una cantidad fija por fotograma. El recurso Time le proporciona delta_secs(), los segundos transcurridos desde el último fotograma.
Multiplicar la velocidad por delta hace que el movimiento sea independiente de la frecuencia de fotogramas.
fn move_player(time: Res<Time>, mut q: Query<&mut Transform, With<Player>>) {
let dt = time.delta_secs();
for mut tf in &mut q {
tf.translation.x += 200.0 * dt;
}
}Combinar entrada y tiempo
El patrón real combina ambos recursos en un sistema: lea la dirección de la entrada y, después, escálela según la velocidad y delta.
Esto produce un control fluido y uniforme, independientemente de si el juego se ejecuta a 30 o a 144 fotogramas por segundo.
fn drive(
keys: Res<ButtonInput<KeyCode>>,
time: Res<Time>,
mut q: Query<&mut Transform, With<Player>>,
) {
let mut d = Vec2::ZERO;
if keys.pressed(KeyCode::KeyA) { d.x -= 1.0; }
if keys.pressed(KeyCode::KeyD) { d.x += 1.0; }
let step = d.normalize_or_zero() * 300.0 * time.delta_secs();
for mut tf in &mut q {
tf.translation += step.extend(0.0);
}
}Botones del ratón
Los botones del ratón utilizan la misma API ButtonInput, con MouseButton en lugar de KeyCode.
Esta coherencia significa que los hábitos con pressed y just_pressed que desarrolló para el teclado se aplican directamente a los clics.
fn shoot(buttons: Res<ButtonInput<MouseButton>>) {
if buttons.just_pressed(MouseButton::Left) {
info!("fire");
}
}Temporizadores para los tiempos de espera
Un Timer realiza un seguimiento del tiempo transcurrido hasta alcanzar una duración objetivo. Actualícelo con el delta del fotograma en cada actualización.
Utilice un temporizador repetitivo para establecer una cadencia de disparo y compruebe just_finished() para saber cuándo actuar.
#[derive(Component)]
struct Cooldown(Timer);
fn tick(time: Res<Time>, mut q: Query<&mut Cooldown>) {
for mut cd in &mut q {
cd.0.tick(time.delta());
if cd.0.just_finished() { info!("ready"); }
}
}Creación de un Timer
Construya un temporizador a partir de una duración y un TimerMode. Once se detiene después de activarse; Repeating se reinicia automáticamente.
Almacénelo en un componente para que cada entidad, como una torreta, pueda tener su propia cadencia independiente.
use std::time::Duration;
commands.spawn((
Turret,
Cooldown(Timer::new(Duration::from_millis(500), TimerMode::Repeating)),
));FixedUpdate para el determinismo
La física y el código de red suelen necesitar un paso de tiempo fijo. Los sistemas de la planificación FixedUpdate se ejecutan un número constante de veces por segundo, independientemente de la frecuencia de renderizado.
Dentro de ellos, utilice Time<Fixed>, cuyo delta siempre es el mismo, para obtener una simulación reproducible.
App::new()
.add_plugins(DefaultPlugins)
.add_systems(FixedUpdate, physics_step)
.run();Tiempo transcurrido frente a delta
time.delta_secs() es el intervalo desde el último fotograma. time.elapsed_secs() es el tiempo total transcurrido desde el inicio.
El tiempo transcurrido resulta ideal para animaciones controladas por una onda sinusoidal, como un objeto coleccionable que sube y baja, en las que se introduce el tiempo total en la función.
fn bob(time: Res<Time>, mut q: Query<&mut Transform, With<Pickup>>) {
let t = time.elapsed_secs();
for mut tf in &mut q {
tf.translation.y = (t * 2.0).sin() * 10.0;
}
}Limitación a los límites
Después de mover al jugador, manténgalo en pantalla limitando el transform dentro de las semidimensiones de la ventana.
f32::clamp limita cada eje. Lea el tamaño de la ventana desde la consulta Window cuando necesite límites exactos.
fn clamp(mut q: Query<&mut Transform, With<Player>>) {
for mut tf in &mut q {
tf.translation.x = tf.translation.x.clamp(-300.0, 300.0);
tf.translation.y = tf.translation.y.clamp(-200.0, 200.0);
}
}Comprobación rápida
Considere la independencia de la frecuencia de fotogramas.
Repaso: entrada y tiempo
La entrada se encuentra en los recursos ButtonInput; utilice pressed para acciones mantenidas y just_pressed para toques. El recurso Time y los componentes Timer mantienen el movimiento y los tiempos de espera independientes de la frecuencia de fotogramas.
Con el control listo, la lección final añade colisiones y transiciones de estado del juego.
Preguntas frecuentes
¿La lección «Gestionar la entrada y el tiempo» es gratis?
Sí — el texto completo de «Gestionar la entrada y el tiempo» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de Learn Rust Coding, actualiza a CoddyKit PRO. El curso de Learn Rust Coding incluye 4 lecciones en total.
¿Qué aprenderé en «Gestionar la entrada y el tiempo»?
Responda al jugador y al reloj Practicas Learn Rust Coding con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.
¿Necesito experiencia previa para empezar Learn Rust Coding?
No se requiere experiencia previa. Learn Rust Coding en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 3 de 4.
¿Cuánto tiempo toma la lección «Gestionar la entrada y el tiempo»?
La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.
¿Puedo escribir y ejecutar código en esta lección de Learn Rust Coding?
Sí. Cada lección de Learn Rust Coding incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.
Todas las lecciones de este curso
- La mentalidad ECS
- Crear y mover entidades
- Gestionar la entrada y el tiempo
- Colisiones y estado del juego