0Pricing
Learn Rust Coding · Aula

Lidando com entrada e tempo

Reaja ao jogador e ao relógio.

Lidando com entrada e tempo é uma aula grátis de Learn Rust Coding no CoddyKit. Esta é a aula 3 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Learn Rust Coding, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Learn Rust Coding inclui 4 aulas no total.

Entrada como recurso

O estado do teclado fica no recurso ButtonInput<KeyCode>, fornecido por DefaultPlugins.

Solicite-o somente para leitura com Res. O Bevy o atualiza a cada quadro antes da execução dos seus sistemas, então você sempre vê o estado atual.

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

pressed vs. just_pressed

pressed é verdadeiro em todos os quadros enquanto uma tecla está pressionada — ideal para movimento contínuo. just_pressed é verdadeiro apenas no quadro em que a tecla é pressionada.

Use just_pressed para ações discretas, como pular ou disparar, para que um único toque dispare uma vez.

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

Construindo um vetor de direção

Combine várias teclas em uma direção de movimento. Comece em zero e adicione uma unidade a cada eixo para cada tecla pressionada.

Normalizar o resultado impede que o movimento diagonal seja mais rápido que o movimento reto.

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

O recurso Time

As taxas de quadros variam de acordo com a máquina, portanto nunca mova algo por uma quantidade fixa a cada quadro. O recurso Time fornece delta_secs(), os segundos desde o último quadro.

Multiplicar a velocidade pelo delta torna o movimento independente da taxa de quadros.

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

Combinando entrada e tempo

O padrão real combina os dois recursos em um sistema: leia a direção da entrada e depois multiplique-a pela velocidade e pelo delta.

Isso produz um controle suave e consistente, independentemente de o jogo ser executado a 30 ou 144 quadros 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);
    }
}

Botões do mouse

Os botões do mouse usam a mesma API ButtonInput, com MouseButton no lugar de KeyCode.

Essa consistência significa que os hábitos de usar pressed e just_pressed que você desenvolveu para o teclado são aplicados diretamente aos cliques.

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

Timers para tempos de recarga

Um Timer acompanha o tempo decorrido em direção a uma duração-alvo. Avance-o com o delta do quadro a cada atualização.

Use um timer repetitivo para controlar a cadência de disparos e verifique just_finished() para saber quando agir.

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

Criando um Timer

Construa um timer a partir de uma duração e de um TimerMode. Once para depois de disparar; Repeating reinicia automaticamente.

Armazene-o em um componente para que cada entidade, como uma torre, possa ter sua própria cadência independente.

use std::time::Duration;

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

FixedUpdate para determinismo

A física e o código de rede geralmente precisam de um intervalo fixo. Os sistemas da programação FixedUpdate são executados um número constante de vezes por segundo, independentemente da taxa de renderização.

Dentro deles, use Time<Fixed>, cujo delta é sempre igual, produzindo uma simulação reproduzível.

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

Tempo decorrido vs. delta

time.delta_secs() é o intervalo desde o último quadro. time.elapsed_secs() é o tempo total desde a inicialização.

O tempo decorrido é ótimo para animações controladas por uma onda senoidal, como um item coletável que oscila, nas quais você fornece o tempo total à função.

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

Limitando aos limites

Depois de mover o jogador, mantenha-o na tela limitando o transform dentro das semidimensões da janela.

f32::clamp limita cada eixo. Leia o tamanho da janela na Window query quando precisar de limites exatos.

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

Verificação rápida

Considere a independência em relação à taxa de quadros.

Recapitulação: entrada e tempo

A entrada fica nos recursos ButtonInput; use pressed para ações mantidas e just_pressed para toques. O recurso Time e os componentes Timer mantêm o movimento e os tempos de recarga independentes da taxa de quadros.

Com o controle pronto, a lição final adiciona colisões e transições de estado do jogo.

Perguntas Frequentes

A aula “Lidando com entrada e tempo” é grátis?

Sim — o texto completo de “Lidando com entrada e tempo” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Learn Rust Coding, atualize para CoddyKit PRO. O curso de Learn Rust Coding inclui 4 aulas no total.

O que vou aprender em “Lidando com entrada e tempo”?

Reaja ao jogador e ao relógio. Você pratica Learn Rust Coding com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.

Preciso ter experiência prévia para começar Learn Rust Coding?

Nenhuma experiência prévia é necessária. Learn Rust Coding no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 3 de 4.

Quanto tempo leva a aula “Lidando com entrada e tempo”?

A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.

Posso escrever e executar código nesta aula de Learn Rust Coding?

Sim. Cada aula de Learn Rust Coding inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.

Todas as aulas deste curso

  1. A mentalidade ECS
  2. Criando e movendo entidades
  3. Lidando com entrada e tempo
  4. Colisões e estado do jogo
← Voltar para Learn Rust Coding