Obsługa wejścia i czasu
Zareaguje Pan/Pani na działania gracza i upływ czasu.
Obsługa wejścia i czasu to bezpłatna lekcja Learn Rust Coding na CoddyKit. To lekcja 3 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Learn Rust Coding, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Learn Rust Coding zawiera 4 lekcji w sumie.
Wejście jako zasób
Stan klawiatury znajduje się w zasobie ButtonInput<KeyCode> dostarczanym przez DefaultPlugins.
Zażądaj do niego dostępu tylko do odczytu za pomocą Res. Bevy aktualizuje go w każdej klatce przed uruchomieniem systemów, więc zawsze widzisz bieżący stan.
fn read_keys(keys: Res<ButtonInput<KeyCode>>) {
if keys.pressed(KeyCode::Space) {
info!("space held");
}
}pressed a just_pressed
pressed ma wartość true w każdej klatce, w której klawisz jest wciśnięty — idealnie nadaje się do ciągłego ruchu. just_pressed ma wartość true tylko w klatce, w której klawisz zostaje wciśnięty.
Używaj just_pressed do działań dyskretnych, takich jak skok lub strzał, aby pojedyncze naciśnięcie wywołało akcję tylko raz.
fn jump(keys: Res<ButtonInput<KeyCode>>) {
if keys.just_pressed(KeyCode::ArrowUp) {
info!("jump!");
}
}Budowanie wektora kierunku
Połącz wiele klawiszy w kierunek ruchu. Zacznij od zera i dodaj jednostkę na każdej osi odpowiadającej wciśniętemu klawiszowi.
Normalizacja wyniku zapobiega temu, aby ruch po skosie był szybszy niż ruch w linii prostej.
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()
}Zasób Time
Liczba klatek na sekundę różni się w zależności od komputera, dlatego nigdy nie należy przesuwać obiektu o stałą wartość w każdej klatce. Zasób Time udostępnia metodę delta_secs() zwracającą liczbę sekund od poprzedniej klatki.
Pomnożenie prędkości przez wartość delta sprawia, że ruch jest niezależny od liczby klatek na sekundę.
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;
}
}Łączenie wejścia i czasu
Rzeczywisty wzorzec łączy oba zasoby w jednym systemie: odczytaj kierunek z wejścia, a następnie przeskaluj go przez prędkość i deltę czasu.
Dzięki temu sterowanie jest płynne i spójne niezależnie od tego, czy gra działa z szybkością 30, czy 144 klatek na sekundę.
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);
}
}Przyciski myszy
Przyciski myszy korzystają z tego samego interfejsu API ButtonInput, używając MouseButton zamiast KeyCode.
Dzięki tej spójności nawyki związane z pressed i just_pressed, wypracowane dla klawiatury, można bezpośrednio zastosować do kliknięć.
fn shoot(buttons: Res<ButtonInput<MouseButton>>) {
if buttons.just_pressed(MouseButton::Left) {
info!("fire");
}
}Timery do obsługi czasu odnowienia
Obiekt Timer śledzi upływ czasu do osiągnięcia określonego czasu trwania. Przy każdej aktualizacji zwiększaj go o deltę klatki.
Użyj powtarzającego się timera do ustalenia częstotliwości strzału i sprawdzaj just_finished(), aby wiedzieć, kiedy wykonać działanie.
#[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"); }
}
}Tworzenie timera
Utwórz timer na podstawie czasu trwania i obiektu TimerMode. Once zatrzymuje się po uruchomieniu, a Repeating automatycznie się resetuje.
Przechowuj go w komponencie, aby każda encja, na przykład wieżyczka, mogła mieć własną, niezależną częstotliwość działania.
use std::time::Duration;
commands.spawn((
Turret,
Cooldown(Timer::new(Duration::from_millis(500), TimerMode::Repeating)),
));FixedUpdate dla determinizmu
Fizyka i kod sieciowy często wymagają stałego kroku czasowego. Systemy w harmonogramie FixedUpdate uruchamiają się stałą liczbę razy na sekundę, niezależnie od częstotliwości renderowania.
W ich obrębie używaj Time<Fixed>, którego delta jest zawsze taka sama, co zapewnia powtarzalność symulacji.
App::new()
.add_plugins(DefaultPlugins)
.add_systems(FixedUpdate, physics_step)
.run();Czas, który upłynął, a delta
time.delta_secs() to odstęp od ostatniej klatki. time.elapsed_secs() to całkowity czas od uruchomienia.
Czas, który upłynął, świetnie nadaje się do animacji sterowanych falą sinusoidalną, na przykład kołyszącego się obiektu do zebrania, gdy do funkcji przekazywany jest całkowity czas.
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;
}
}Ograniczanie do granic
Po wykonaniu ruchu utrzymaj gracza na ekranie, ograniczając transformację do połowy wymiarów okna.
f32::clamp ogranicza każdą oś. Gdy potrzebujesz dokładnych granic, odczytaj rozmiar okna z zapytania Window.
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);
}
}Szybkie sprawdzenie
Rozważ niezależność od liczby klatek na sekundę.
Podsumowanie: wejście i czas
Wejście znajduje się w zasobach ButtonInput. Używaj pressed dla działań wykonywanych podczas przytrzymania oraz just_pressed dla pojedynczych naciśnięć. Zasób Time i komponenty Timer zapewniają niezależność ruchu i czasu odnowienia od liczby klatek na sekundę.
Po opanowaniu sterowania ostatnia lekcja doda kolizje i przejścia między stanami gry.
Często zadawane pytania
Czy lekcja „Obsługa wejścia i czasu” jest bezpłatna?
Tak — pełny tekst „Obsługa wejścia i czasu” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Learn Rust Coding, przejdź na CoddyKit PRO. Kurs Learn Rust Coding zawiera 4 lekcji w sumie.
Co nauczysz się w „Obsługa wejścia i czasu”?
Zareaguje Pan/Pani na działania gracza i upływ czasu. Ćwiczysz Learn Rust Coding z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć Learn Rust Coding?
Nie wymagamy żadnego doświadczenia. Learn Rust Coding w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 3 z 4.
Ile czasu zajmuje lekcja „Obsługa wejścia i czasu”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji Learn Rust Coding?
Tak. Każda lekcja Learn Rust Coding zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- Sposób myślenia ECS
- Tworzenie i poruszanie encjami
- Obsługa wejścia i czasu
- Kolizje i stan gry