0Pricing
Learn Rust Coding · Leçon

Gérer les entrées et le temps

Réagissez au joueur et à l’horloge.

Gérer les entrées et le temps est une leçon Learn Rust Coding gratuite sur CoddyKit. Ceci est la leçon 3 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage Learn Rust Coding, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours Learn Rust Coding comprend 4 leçons au total.

Certaines parties de cette leçon n'ont pas encore été traduites et s'affichent en anglais.

Input as a Resource

Keyboard state lives in the ButtonInput<KeyCode> resource, provided by DefaultPlugins.

Request it read-only with Res. Bevy updates it each frame before your systems run, so you always see the current state.

fn read_keys(keys: Res<ButtonInput<KeyCode>>) {
    if keys.pressed(KeyCode::Space) {
        info!("space held");
    }
}

pressed vs just_pressed

pressed is true every frame a key is held — ideal for continuous movement. just_pressed is true only on the frame the key goes down.

Use just_pressed for discrete actions like jumping or firing so a single tap fires once.

fn jump(keys: Res<ButtonInput<KeyCode>>) {
    if keys.just_pressed(KeyCode::ArrowUp) {
        info!("jump!");
    }
}

Building a Direction Vector

Combine multiple keys into a movement direction. Start at zero and add a unit on each axis for each pressed key.

Normalizing the result prevents diagonal movement from being faster than straight movement.

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()
}

The Time Resource

Frame rates vary by machine, so never move by a fixed amount per frame. The Time resource gives you delta_secs(), the seconds since the last frame.

Multiplying speed by delta makes movement frame-rate independent.

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;
    }
}

Combining Input and Time

The real pattern joins both resources in one system: read the direction from input, then scale it by speed and delta.

This produces smooth, consistent control regardless of whether the game runs at 30 or 144 frames per second.

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);
    }
}

Mouse Buttons

Mouse buttons use the same ButtonInput API with MouseButton instead of KeyCode.

This consistency means the pressed and just_pressed habits you built for the keyboard transfer directly to clicks.

fn shoot(buttons: Res<ButtonInput<MouseButton>>) {
    if buttons.just_pressed(MouseButton::Left) {
        info!("fire");
    }
}

Timers for Cooldowns

A Timer tracks elapsed time toward a target duration. Tick it with the frame delta each update.

Use a repeating timer for a firing cadence and check just_finished() to know when to act.

#[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"); }
    }
}

Creating a Timer

Construct a timer from a duration and a TimerMode. Once stops after firing; Repeating resets automatically.

Store it on a component so each entity, such as a turret, can have its own independent cadence.

use std::time::Duration;

commands.spawn((
    Turret,
    Cooldown(Timer::new(Duration::from_millis(500), TimerMode::Repeating)),
));

FixedUpdate for Determinism

Physics and netcode often need a fixed timestep. Systems in the FixedUpdate schedule run a constant number of times per second, regardless of render rate.

Inside them, use Time<Fixed> whose delta is always the same, giving reproducible simulation.

App::new()
    .add_plugins(DefaultPlugins)
    .add_systems(FixedUpdate, physics_step)
    .run();

Elapsed vs Delta

time.delta_secs() is the gap since last frame. time.elapsed_secs() is the total time since startup.

Elapsed is great for animations driven by a sine wave, like a bobbing pickup, where you feed total time into the function.

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;
    }
}

Clamping to Bounds

After moving, keep the player on screen by clamping the transform within the window's half-extents.

f32::clamp bounds each axis. Read the window size from the Window query when you need exact limits.

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);
    }
}

Quick Check

Consider frame-rate independence.

Recap: Input and Time

Input lives in ButtonInput resources; use pressed for held actions and just_pressed for taps. The Time resource and Timer components keep movement and cooldowns frame-rate independent.

With control in place, the final lesson adds collisions and game state transitions.

Questions Fréquemment Posées

La leçon « Gérer les entrées et le temps » est-elle gratuite ?

Oui — le texte complet de « Gérer les entrées et le temps » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours Learn Rust Coding, passe à CoddyKit PRO. Le cours Learn Rust Coding comprend 4 leçons au total.

Qu'est-ce que j'apprendrai dans « Gérer les entrées et le temps » ?

Réagissez au joueur et à l’horloge. Tu pratiques Learn Rust Coding avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.

Dois-je avoir de l'expérience pour commencer Learn Rust Coding ?

Aucune expérience préalable n'est requise. Learn Rust Coding sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 3 sur 4.

Combien de temps prend la leçon « Gérer les entrées et le temps » ?

La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.

Peux-tu écrire et exécuter du code dans cette leçon Learn Rust Coding ?

Oui. Chaque leçon Learn Rust Coding inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.

Toutes les leçons de ce cours

  1. La philosophie ECS
  2. Créer et déplacer des entités
  3. Gérer les entrées et le temps
  4. Collisions et état du jeu
← Retour à Learn Rust Coding