用 Rust 開發遊戲 - 4 跳躍

在《用 Rust 開發遊戲 - 3 地面和重力》部分我們添加了重力和碰撞檢測。這一部分將實現如何跳躍。

跳躍基礎

我們將從定義跳躍組件開始,這個組件集中了所有跳躍邏輯。

struct Jumper {
    jump_impulse: f32,
}

在 spawn_player 方法中,我們將把這個新組件添加到玩家中:

.insert(Jumper { jump_impulse: 10. });

然後我們將添加一個玩家跳躍系統並將其註冊到我們的應用程序中:

// In main, register a player movement system
.add_system(player_jumps.system())
// Define a player movement system
fn player_jumps(
    keyboard_input: Res<Input<KeyCode>>,
    mut players: Query<(&Jumper, &mut RigidBodyVelocity), With<Player>>
) {
    for (jumper, mut velocity) in players.iter_mut() {
        if keyboard_input.pressed(KeyCode::Up) {
            velocity.linvel = Vec2::new(0., jumper.jump_impulse).into();
        }
    }
}

keyboard_input: Res<Input> 參數檢測我們按下的鍵。

mut players: Query<(&Jumper, &mut RigidBodyVelocity), With> 參數返回所有帶有 Jumper, RigidBodyVelocity 和 Player 組件的實體。

該方法中的代碼將玩家的向上速度設置爲 Jumper 組件上定義的 jump_impulse。

如果你運行 cargo run,並按下向上鍵,你應該看到我們的玩家上升,然後下降,直到到達地面。

禁用多個跳躍

在我們當前的代碼中,如果你一直按上鍵,玩家就會一直往上走,直到鬆開爲止。我們需要一種方法去阻止玩家在空中時跳躍。

一種方法是給 Jumper 組件添加一個 is_jumping 布爾屬性。

struct Jumper {
    jump_impulse: f32,
    is_jumping: bool
}
// ...
.insert(Jumper { jump_impulse: 10., is_jumping: false })

然後,只有當布爾值爲 false 時,我們才允許跳躍,當玩家在空中時,我們將該值設爲 true。

fn player_jumps(
    keyboard_input: Res<Input<KeyCode>>,
    mut players: Query<(&mut Jumper, &mut RigidBodyVelocity), With<Player>>
) {
    for (mut jumper, mut velocity) in players.iter_mut() {
        if keyboard_input.pressed(KeyCode::Up) && !jumper.is_jumping {
            velocity.linvel = Vec2::new(0., jumper.jump_impulse).into();
            jumper.is_jumping = true
        }
    }
}

如果你運行應用程序,玩家在空中就不能再跳。唯一的問題是它只能跳一次……

當玩家停止跳躍的時候,我們需要一種重置 is_jumping 標誌的方法。

重置標誌

爲了做到這一點,Rapier 擁有一個事件系統,即當兩個實體發生接觸時便會觸發事件。我們將利用它重置我們的標誌。

添加一個新的 jump_reset 系統,並在我們的應用程序中註冊它:

// In main
.add_system(jump_reset.system())
// ...
pub fn jump_reset(
    mut query: Query<(Entity, &mut Jumper)>,
    mut contact_events: EventReader<ContactEvent>,
) {
    for contact_event in contact_events.iter() {
        for (entity, mut jumper) in query.iter_mut() {
            set_jumping_false_if_touching_floor(entity, &mut jumper, contact_event);
        }
    }
}
fn set_jumping_false_if_touching_floor(entity: Entity, jumper: &mut Jumper, event: &ContactEvent) {
    if let ContactEvent::Started(h1, h2) = event {
        if h1.entity() == entity || h2.entity() == entity {
            jumper.is_jumping = false
        }
    }
}

這個系統檢索所有跳躍組件和所有發生的接觸事件。然後,它會查看其中一個接觸事件是否涉及給定的跳躍者。如果是這樣,它將 Jumper 的 is_jump 設置爲 false。

如果我們想要實現這一點,我們就需要激活玩家碰撞器的接觸事件:

flags: ColliderFlags {
    active_events: ActiveEvents::CONTACT_EVENTS,
    ..Default::default()
},

運行 cargo run ,按下鍵盤上的 up 鍵。我們的玩家不能再雙跳了,它可以在觸地後重新跳躍。

本文翻譯自:

https://dev.to/sbelzile/making-games-in-rust-part-4-jumps-2jne

coding 到燈火闌珊 專注於技術分享,包括 Rust、Golang、分佈式架構、雲原生等。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/gI6pMW4zBHOfpwkK0LJcdA