0Pricing
Learn Rust Coding · บทเรียน

จัดการข้อมูลนำเข้าและเวลา

ตอบสนองต่อผู้เล่นและนาฬิกา

จัดการข้อมูลนำเข้าและเวลา เป็นบทเรียน Learn Rust Coding ฟรีบน CoddyKit นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Learn Rust Coding และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Learn Rust Coding มีบทเรียนทั้งหมด 4 บทเรียน

อินพุตในฐานะทรัพยากร

สถานะแป้นพิมพ์อยู่ในทรัพยากร ButtonInput<KeyCode> ซึ่งจัดเตรียมโดย DefaultPlugins

ขอการเข้าถึงแบบอ่านอย่างเดียวด้วย Res Bevy จะอัปเดตทรัพยากรนี้ในแต่ละเฟรมก่อนที่ระบบของคุณจะทำงาน คุณจึงเห็นสถานะปัจจุบันอยู่เสมอ

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

pressed กับ just_pressed

pressed เป็นจริงทุกเฟรมที่กดปุ่มค้างไว้ จึงเหมาะกับการเคลื่อนที่ต่อเนื่อง ส่วน just_pressed เป็นจริงเฉพาะเฟรมที่ปุ่มถูกกดลง

ใช้ just_pressed กับการกระทำที่เกิดเป็นครั้ง ๆ เช่น การกระโดดหรือการยิง เพื่อให้การแตะปุ่มหนึ่งครั้งทำงานเพียงครั้งเดียว

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

การสร้างเวกเตอร์ทิศทาง

รวมปุ่มหลายปุ่มเข้าด้วยกันเพื่อสร้างทิศทางการเคลื่อนที่ เริ่มจากศูนย์ แล้วเพิ่มค่าหนึ่งหน่วยในแต่ละแกนสำหรับปุ่มที่ถูกกด

ทำให้ผลลัพธ์เป็นเวกเตอร์หน่วย เพื่อป้องกันไม่ให้การเคลื่อนที่แนวทแยงเร็วกว่าแนวตรง

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

ทรัพยากรเวลา

อัตราเฟรมแตกต่างกันไปตามเครื่อง ดังนั้นอย่าเคลื่อนที่ด้วยจำนวนคงที่ต่อเฟรม ทรัพยากร Time ให้ค่า delta_secs() ซึ่งคือจำนวนวินาทีตั้งแต่เฟรมก่อนหน้า

การคูณความเร็วด้วยค่า delta ทำให้การเคลื่อนที่ไม่ขึ้นกับอัตราเฟรม

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

การรวมอินพุตกับเวลา

รูปแบบที่ถูกต้องคือรวมทรัพยากรทั้งสองไว้ในระบบเดียว: อ่านทิศทางจากอินพุต แล้วคูณด้วยความเร็วและ delta

วิธีนี้ทำให้การควบคุมราบรื่นและสม่ำเสมอ ไม่ว่าเกมจะทำงานที่ 30 หรือ 144 เฟรมต่อวินาทีก็ตาม

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

ปุ่มเมาส์

ปุ่มเมาส์ใช้ API ButtonInput เดียวกัน โดยใช้ MouseButton แทน KeyCode

ความสอดคล้องนี้ทำให้แนวทางการใช้ pressed และ just_pressed ที่คุณเรียนรู้จากแป้นพิมพ์ นำมาใช้กับการคลิกได้โดยตรง

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

ตัวจับเวลาสำหรับช่วงหน่วงเวลา

Timer ใช้ติดตามเวลาที่ผ่านไปจนถึงระยะเวลาที่กำหนด ให้เพิ่มค่าเวลาโดยใช้ delta ของเฟรมในการอัปเดตแต่ละครั้ง

ใช้ตัวจับเวลาแบบทำซ้ำเพื่อกำหนดจังหวะการยิง และตรวจสอบ just_finished() เพื่อดูว่าถึงเวลาทำงานแล้วหรือไม่

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

การสร้าง Timer

สร้างตัวจับเวลาจากระยะเวลาและ TimerMode โดย Once จะหยุดหลังทำงานครั้งแรก ส่วน Repeating จะเริ่มนับใหม่โดยอัตโนมัติ

เก็บตัวจับเวลาไว้ในคอมโพเนนต์ เพื่อให้แต่ละเอนทิตี เช่น ป้อมปืน มีจังหวะการทำงานของตนเองอย่างเป็นอิสระ

use std::time::Duration;

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

FixedUpdate เพื่อความเป็นกำหนดแน่นอน

ฟิสิกส์และระบบเครือข่ายมักต้องใช้ช่วงเวลาคงที่ ระบบในกำหนดการ FixedUpdate จะทำงานด้วยจำนวนครั้งต่อวินาทีที่คงที่ ไม่ว่าอัตราการเรนเดอร์จะเป็นเท่าใด

ภายในระบบเหล่านี้ ให้ใช้ Time<Fixed> ซึ่งมี delta เท่ากันเสมอ ทำให้การจำลองได้ผลลัพธ์ซ้ำเดิม

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

เวลาที่ผ่านไปกับ delta

time.delta_secs() คือช่วงเวลาตั้งแต่เฟรมก่อนหน้า ส่วน time.elapsed_secs() คือเวลารวมตั้งแต่เริ่มต้นโปรแกรม

เวลาที่ผ่านไปเหมาะอย่างยิ่งสำหรับแอนิเมชันที่ขับเคลื่อนด้วยคลื่นไซน์ เช่น ไอเท็มที่ลอยขึ้นลง โดยป้อนเวลารวมเข้าไปในฟังก์ชัน

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

จำกัดค่าให้อยู่ในขอบเขต

หลังจากเคลื่อนที่แล้ว ให้ผู้เล่นอยู่ภายในหน้าจอด้วยการจำกัดค่า transform ให้อยู่ภายในระยะครึ่งหนึ่งของขนาดหน้าต่าง

f32::clamp จะจำกัดค่าในแต่ละแกน อ่านขนาดหน้าต่างจากคิวรี 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);
    }
}

ตรวจสอบความเข้าใจอย่างรวดเร็ว

ลองพิจารณาการทำงานที่ไม่ขึ้นกับอัตราเฟรม

ทบทวน: อินพุตและเวลา

อินพุตอยู่ในทรัพยากร ButtonInput ให้ใช้ pressed สำหรับการทำงานที่กดค้าง และใช้ just_pressed สำหรับการกดครั้งเดียว ทรัพยากร Time และคอมโพเนนต์ Timer ช่วยให้การเคลื่อนที่และช่วงหน่วงเวลาไม่ขึ้นกับอัตราเฟรม

เมื่อการควบคุมพร้อมแล้ว บทเรียนสุดท้ายจะเพิ่มการชนและการเปลี่ยนสถานะของเกม

คำถามที่พบบ่อย

บทเรียน “จัดการข้อมูลนำเข้าและเวลา” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “จัดการข้อมูลนำเข้าและเวลา” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Learn Rust Coding ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Learn Rust Coding มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “จัดการข้อมูลนำเข้าและเวลา”

ตอบสนองต่อผู้เล่นและนาฬิกา คุณปฏิบัติ Learn Rust Coding ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Learn Rust Coding หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน Learn Rust Coding บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน

บทเรียน “จัดการข้อมูลนำเข้าและเวลา” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน Learn Rust Coding นี้ได้ไหม

ได้ บทเรียน Learn Rust Coding ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. แนวคิดแบบ ECS
  2. สร้างและเคลื่อนย้ายเอนทิตี
  3. จัดการข้อมูลนำเข้าและเวลา
  4. การชนและสถานะเกม
← กลับไปที่ Learn Rust Coding