การชนและสถานะเกม
เพิ่มกฎและเงื่อนไขชนะ
การชนและสถานะเกม เป็นบทเรียน Learn Rust Coding ฟรีบน CoddyKit นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Learn Rust Coding และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Learn Rust Coding มีบทเรียนทั้งหมด 4 บทเรียน
พื้นฐานการชนแบบ AABB
การทดสอบการชนที่ง่ายที่สุดคือการตรวจสอบการทับซ้อนของกรอบล้อมรอบที่จัดแนวตามแกน (AABB) สี่เหลี่ยมสองรูปจะชนกันเมื่อทับซ้อนกันทั้งบนแกน x และแกน y
สำหรับสไปรต์ วิธีนี้ทำงานได้รวดเร็วและเพียงพอสำหรับเกม 2 มิติจำนวนมาก ก่อนที่จะเลือกใช้เอนจินฟิสิกส์เต็มรูปแบบ
fn overlaps(a_pos: Vec2, a_size: Vec2, b_pos: Vec2, b_size: Vec2) -> bool {
(a_pos.x - b_pos.x).abs() < (a_size.x + b_size.x) * 0.5
&& (a_pos.y - b_pos.y).abs() < (a_size.y + b_size.y) * 0.5
}คอมโพเนนต์ Collider
เพิ่มคอมโพเนนต์ Collider ที่เก็บระยะครึ่งหนึ่งของขนาดหรือขนาดเต็มของแต่ละเอนทิตี จากนั้นระบบจะอ่าน transform ร่วมกับ collider เพื่อตรวจสอบการทับซ้อน
การเก็บขนาดไว้ในคอมโพเนนต์แยกต่างหาก ทำให้เอนทิตีต่างชนิดใช้ระบบตรวจจับการชนเดียวกันได้
#[derive(Component)]
struct Collider {
size: Vec2,
}การตรวจจับการชนในระบบ
หากต้องการเปรียบเทียบผู้เล่นกับสิ่งกีดขวางจำนวนมาก ให้คิวรีผู้เล่นหนึ่งครั้งแล้ววนซ้ำผ่านสิ่งกีดขวาง การใช้คิวรีแยกกันสองรายการช่วยหลีกเลี่ยงการยืมข้อมูลชุดเดียวกันซ้ำ
เมื่อเกิดการทับซ้อน คุณสามารถตอบสนองด้วยการสร้างความเสียหาย การกระเด้ง หรือการนำออกจากฉาก ผ่าน Commands หรือการแก้ไขคอมโพเนนต์
fn detect(
player: Query<(&Transform, &Collider), With<Player>>,
walls: Query<(&Transform, &Collider), With<Wall>>,
) {
let (pt, pc) = player.single().unwrap();
for (wt, wc) in &walls {
if overlaps(pt.translation.truncate(), pc.size, wt.translation.truncate(), wc.size) {
info!("hit a wall");
}
}
}การตอบสนองด้วยเหตุการณ์
แทนที่จะจัดการผลลัพธ์ที่ตามมาภายในระบบเดียว ให้ส่ง Event แบบกำหนดเอง ระบบหนึ่งจะตรวจจับการชนและส่งเหตุการณ์ ส่วนอีกระบบจะอ่านเหตุการณ์และนำผลไปใช้
วิธีนี้แยกการตรวจจับออกจากการตอบสนอง และทำให้แต่ละระบบมีขนาดเล็ก
#[derive(Event)]
struct CollisionEvent { entity: Entity }
fn emit(mut writer: EventWriter<CollisionEvent>, e: Entity) {
writer.send(CollisionEvent { entity: e });
}การอ่านเหตุการณ์
ระบบตัวอ่านจะดึงเหตุการณ์ที่รออยู่ด้วย EventReader แล้วดำเนินการกับแต่ละเหตุการณ์ เหตุการณ์จะคงอยู่เป็นเวลาสองเฟรม ดังนั้นตัวอ่านทุกตัวจึงมองเห็นเหตุการณ์เหล่านั้น
กระบวนการเผยแพร่และสมัครรับนี้ขยายระบบได้ดี โดยมีผู้ส่งหลายรายและผู้รับหลายรายโดยไม่ต้องผูกกันแน่นเกินไป
fn on_hit(mut reader: EventReader<CollisionEvent>, mut commands: Commands) {
for ev in reader.read() {
commands.entity(ev.entity).despawn();
}
}การอัปเดตคะแนน
เมื่อผู้เล่นเก็บไอเท็มได้ ให้แก้ไขทรัพยากรส่วนกลาง Score ด้วย ResMut
เนื่องจากทรัพยากรมีได้เพียงหนึ่งชุด ระบบใด ๆ ก็สามารถอ่านหรืออัปเดตคะแนนได้โดยไม่ต้องส่งต่อด้วยตนเอง
fn collect(mut score: ResMut<Score>, mut reader: EventReader<PickupEvent>) {
for _ in reader.read() {
score.0 += 10;
}
}สถานะ: ภาพรวมสำคัญ
เกมจะเปลี่ยนไปมาระหว่างโหมดต่าง ๆ เช่น เมนู กำลังเล่น หยุดชั่วคราว และจบเกม Bevy จำลองสิ่งเหล่านี้ด้วย enum States ที่ลงทะเบียนผ่าน init_state
ในแต่ละช่วงเวลาจะมีสถานะที่ทำงานอยู่เพียงหนึ่งสถานะ และสามารถกำหนดให้ระบบทำงานเฉพาะในสถานะที่ระบุได้
#[derive(States, Default, Debug, Clone, PartialEq, Eq, Hash)]
enum GameState {
#[default]
Menu,
Playing,
GameOver,
}การลงทะเบียนสถานะ
เพิ่มสถานะลงในแอปด้วย init_state จากนั้น Bevy จะติดตามค่าปัจจุบันและจัดเตรียมทรัพยากร State กับ NextState ให้
อ่านสถานะปัจจุบันด้วย Res<State<GameState>> เมื่อระบบจำเป็นต้องทราบโหมดที่กำลังทำงาน
App::new()
.add_plugins(DefaultPlugins)
.init_state::<GameState>()
.run();การเรียกใช้ระบบในสถานะหนึ่ง
กำหนดให้ระบบทำงานเฉพาะในสถานะหนึ่งด้วยเงื่อนไข run_if และ in_state การเคลื่อนที่และการชนจะทำงานเฉพาะขณะที่อยู่ใน Playing
นี่คือวิธีทำงานของการหยุดชั่วคราว: หยุดระบบการเล่นโดยออกจากสถานะ Playing แล้วระบบเหล่านั้นก็จะไม่ทำงาน
app.add_systems(
Update,
(drive, detect).run_if(in_state(GameState::Playing)),
);การเปลี่ยนสถานะ
หากต้องการเปลี่ยนสถานะ ให้กำหนดค่า NextState จากระบบใดก็ได้ Bevy จะใช้การเปลี่ยนสถานะเมื่อเริ่มเฟรมถัดไป
ใช้กำหนดการ OnEnter และ OnExit เพื่อสร้างส่วนติดต่อผู้ใช้เมื่อเข้าสู่สถานะ หรือทำความสะอาดเมื่อออกจากสถานะ
fn lose(mut next: ResMut<NextState<GameState>>, health: Res<Health>) {
if health.0 == 0 {
next.set(GameState::GameOver);
}
}ทำความสะอาดเมื่อออกจากสถานะ
เมื่อออกจาก Playing ให้นำเอนทิตีของการเล่นออกจากฉาก เพื่อให้รอบถัดไปเริ่มต้นอย่างสะอาด ติดป้ายกำกับเอนทิตีเหล่านั้นด้วยเครื่องหมาย แล้วนำทุกเอนทิตีที่มีเครื่องหมายนั้นออก
ลงทะเบียนการทำความสะอาดใน OnExit(GameState::Playing) เพื่อให้ทำงานเพียงครั้งเดียวต่อการเปลี่ยนสถานะ
fn cleanup(mut commands: Commands, q: Query<Entity, With<GameEntity>>) {
for e in &q {
commands.entity(e).despawn();
}
}
// app.add_systems(OnExit(GameState::Playing), cleanup);ตรวจสอบความเข้าใจอย่างรวดเร็ว
ลองพิจารณาวิธีหยุดการเล่นชั่วคราวอย่างเป็นระเบียบ
ทบทวน: การชนและสถานะของเกม
การทดสอบ AABB ร่วมกับคอมโพเนนต์ Collider ใช้ตรวจจับการทับซ้อน เหตุการณ์ช่วยแยกการตรวจจับออกจากการตอบสนอง และทรัพยากร Score ใช้ติดตามความคืบหน้า ระบบ States พร้อมด้วย run_if, NextState และ OnEnter/OnExit ช่วยจัดโครงสร้างเมนู การเล่น และสถานะจบเกม
ตอนนี้คุณมีวงจรการทำงานครบถ้วนแล้ว: สร้าง ควบคุม ตรวจจับการชน และเปลี่ยนสถานะ จงสร้างเกม Bevy ให้สมบูรณ์จากองค์ประกอบเหล่านี้
เรียนรู้ Rust ด้วย AI tutor — ฟรี
เขียนและเรียกใช้โค้ดจริงในเบราว์เซอร์ของคุณ รับความช่วยเหลือทันทีจาก AI tutor 24/7 และเรียนรู้ต่อจากที่คุณหยุดบนเว็บหรือในแอป
- คอร์ส
- 39
- บทเรียน
- 144
คำถามที่พบบ่อย
บทเรียน “การชนและสถานะเกม” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “การชนและสถานะเกม” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ 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 ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน
บทเรียน “การชนและสถานะเกม” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน Learn Rust Coding นี้ได้ไหม
ได้ บทเรียน Learn Rust Coding ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- แนวคิดแบบ ECS
- สร้างและเคลื่อนย้ายเอนทิตี
- จัดการข้อมูลนำเข้าและเวลา
- การชนและสถานะเกม