iT邦幫忙

2025 iThome 鐵人賽

DAY 17
1
Rust

Bevy Rogue-lite 勇者冒險篇 × Rust 遊戲開發筆記系列 第 17

裝備系統與武器定位

  • 分享至 

  • xImage
  •  

目前為止,都還沒有碰到關於裝備的部分,既然已經做到寶箱的這個階段,那麼寶箱不再只是掉藥水,而是能提供盾牌並直接替玩家增加防禦。另外,也趁機重新整理劍與盾的顯示方式,確保走路時的視覺保持一致。

預計達成的目標:

  • 在地圖上放入兩個示範寶箱,分別掉落不同等級的盾牌。
  • 建立裝備盾牌的事件流程,更新玩家防禦並換上對應的 sprite。
  • 固定劍的位置與朝向,避免角色移動時武器跟著轉向。

兩個盾牌示範寶箱

先放兩個盾牌的素材到專案中:

盾牌素材

new_demo/src/systems/chest.rs 原本會隨機生成寶箱,今天改成 spawn_shield_demo_chests,直接挑選最靠近房間中心的兩塊地板,生成一級與二級盾牌。

let chest_loadout = [ShieldKind::Level1, ShieldKind::Level2];
for (index, kind) in chest_loadout.iter().enumerate() {
    let Some(base_position) = positions.get(index) else { break };
    commands.spawn((
        Chest::new(ChestContents::Item(PickupEffect::EquipShield(*kind))),
        Sprite::from_image(asset_server.load("items/chests/chest_closed.png")),
        Transform::from_translation(Vec3::new(base_position.x, base_position.y, CHEST_Z))
            .with_scale(Vec3::splat(CHEST_SCALE)),
        Name::new(format!("{}Chest", kind.display_name())),
    ));
}

流程與上一篇類似,按空白鍵打開寶箱後,ChestItemReveal 計時 2 秒,時間到就丟出 PickupEffect::EquipShield


ShieldEquipEvent + EquipmentPlugin

新增的 new_demo/src/components/equipment.rs 定義 ShieldKindEquippedShieldShieldVisual Component。核心邏輯放在 new_demo/src/systems/equipment.rs

  1. ShieldEquipEvent 由兩個來源送出:寶箱 (chest_item_reveal_system) 與地上的拾取物 (player_pickup_detection_system)。
  2. handle_shield_equip_events 讀取目前裝備的盾牌,算出新的防禦加成 (kind.defense_bonus()),呼叫 Defense::adjust_bonus 更新屬性。
  3. 若角色身上已有舊的 ShieldVisual 子節點,就先刪除再生成新的 sprite,保持畫面上只有一面盾。
for event in events.read() {
    let new_bonus = event.kind.defense_bonus();
    defense.adjust_bonus(new_bonus - current_bonus);

    commands
        .entity(player_entity)
        .insert(EquippedShield::new(event.kind));

    // 重新掛上盾牌 sprite
    let shield_entity = commands
        .spawn((
            ShieldVisual,
            Sprite::from_image(asset_server.load(event.kind.sprite_path())),
            Transform::from_translation(Vec3::new(SHIELD_OFFSET_X, SHIELD_OFFSET_Y, SHIELD_Z))
                .with_scale(Vec3::splat(SHIELD_SCALE)),
        ))
        .id();
    commands.entity(player_entity).add_child(shield_entity);

    current_bonus = new_bonus;
}

為了把裝備的管線和其他系統解耦,新增 EquipmentPlugin (new_demo/src/plugins/equipment.rs),在 Update 排程裡讓 handle_shield_equip_events 跟在 chest_item_reveal_systemplayer_pickup_detection_system 後面執行。


劍與盾的定位常數

新增的常數集中在 new_demo/src/constants.rs

pub const WEAPON_IDLE_OFFSET_X: f32 = 10.0;
pub const WEAPON_IDLE_OFFSET_Y: f32 = 4.0;
pub const WEAPON_Z: f32 = 1.0;

pub const SHIELD_OFFSET_X: f32 = -8.0;
pub const SHIELD_OFFSET_Y: f32 = -1.0;
pub const SHIELD_Z: f32 = 1.0;

原本角色在往四周移動時,劍會朝著不同方向,但因為希望左手拿的是盾牌,右手拿劍,所以需要讓劍維持在固定的位置,可能會是比較簡易且方便的做法。

  • 劍的位置由 update_weapon_offset_system 直接套用常數,而不再依照 PlayerFacing 更新,因此往任何方向走都是同一個 sprite、同一個角度。揮劍動畫仍使用 WeaponSwing 計時轉動,但基準角度固定為 0.0
  • 盾牌的 sprite 則由前述的裝備系統生成,掛在玩家子節點,偏移量讀自 SHIELD_OFFSET_X/Y,確保位置固定在角色左側。

劍維持在右手的位置

偏移量調整出來的結果。


實際 Demo

開寶箱裝備盾牌

打開寶箱會先看到盾牌 sprite 飄在箱子上方,計時結束後,角色立刻換上左側盾牌並把防禦數值加上 4 或 8。而劍固定位置之後,玩家往上/下/左移動時,畫面不會再出現劍跟著旋轉的奇怪姿勢,揮刀動畫也更好辨識。


小結

這篇的重點是把裝備當成完整的資料流:

  • 寶箱 → PickupEffect::EquipShieldShieldEquipEvent → 防禦數值、盾牌 sprite。
  • 劍與盾的偏移量改成常數控制,未來若更換角色尺寸或素材,只要調整 constants.rs 的數值即可。
  • 新增 EquipmentPlugin 讓裝備相關邏輯獨立管理,後續可以在同一插件下擴充武器、飾品等系統。

打開寶箱拿到盾牌這個流程,預計不會出現在一般寶箱中,而是會在 boss 戰之後的獎勵,所以希望在剩下的篇章可以順利完成這個環節。

今日程式碼同步至 repo


上一篇
開寶箱與寶箱怪
下一篇
武器升級系統
系列文
Bevy Rogue-lite 勇者冒險篇 × Rust 遊戲開發筆記18
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言