iT邦幫忙

2025 iThome 鐵人賽

DAY 26
1
Rust

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

UI 介面統整與圖像化

  • 分享至 

  • xImage
  •  

30 天快接近尾聲了,該準備進到收尾以及調整了,這篇的重點是整理左側 HUD。把原本一大串文字、除錯快捷鍵通通整理成乾淨的介面,並用圖示呈現攻擊、防禦、狀態,讓玩家專注在遊戲本身。另外也補上基本的操作提示,避免新玩家不知道怎麼上手。

這回的重點分成:

  • 將 UI 字型統一,並使用英文介面確保字體一致。
  • 新增 icons/sword.pngicons/shield.pngicons/skull.png,並在面板內以圖示取代純文字欄位。
  • 重寫玩家狀態面板 layout,刪掉 stamina 屬性調整的測試熱鍵顯示。
  • 清理所有 debug 輸入系統,避免玩家誤觸。
  • 在狀態橫幅顯示「Space: Attack / Interact」「Esc: Pause」,並在中毒時顯示 icon 與提示文字。

資訊減量 + 操作提示

之前面板裡塞滿了測試時用的按鍵說明,甚至還顯示耐力數值和攻擊成本,這些在實際操作時會造成視覺混亂:

  • 玩家已經有血條 / 耐力條,不需要再顯示一堆數值。
  • 除錯熱鍵容易被玩家誤按,還會直接改變角色屬性。

因此這波改版的策略是減量、視覺化、只留下必要提示。操作提示改成放在血條下方的細體橫幅,平時只留下 Space/ESC 功能,狀態異常時再額外說明就好。


字型整合與資產調整

new_demo/src/constants.rs 增加了統一字型與圖示的常數:

pub const PLAYER_DEATH_FONT_PATH: &str = "fonts/Kenney-Future-Square.ttf";
pub const MENU_FONT_PATH: &str = "fonts/Kenney-Future-Square.ttf";
pub const PLAYER_STATS_FONT_PATH: &str = "fonts/Kenney-Future-Square.ttf";
pub const PLAYER_STATS_ICON_SIZE: f32 = 28.0;
pub const PLAYER_STATS_ATTACK_ICON_PATH: &str = "icons/sword.png";
pub const PLAYER_STATS_DEFENSE_ICON_PATH: &str = "icons/shield.png";
pub const PLAYER_STATS_POISON_ICON_PATH: &str = "icons/skull.png";
  • 字型路徑改為單一來源,死亡畫面、主選單、HUD 都採同一套英文字型。
  • 三種圖示集中在 assets/icons/,讓面板用 icon 顯示而非一堆縮寫。

統一字型

後續只要改常數就能套用到所有 UI 節點,不用再逐一修改。


Stats 面板改版

player_stats.rs 原本只有一行 Text,現在改成完整的 Flex Column 結構,每個指標都拆成獨立元件:

commands
    .spawn((
        PlayerStatsPanel,
        Node {
            width: Val::Px(PLAYER_STATS_PANEL_WIDTH),
            flex_direction: FlexDirection::Column,
            row_gap: Val::Px(8.0),
            ..Default::default()
        },
        BackgroundColor(Color::srgba(0.05, 0.05, 0.08, 0.92)),
    ))
    .with_children(|parent| {
        parent.spawn((PlayerStatsTitleText, Text::new("PLAYER"), font.clone(), title_color));

        parent
            .spawn((
                Node {
                    width: Val::Percent(100.0),
                    display: Display::Flex,
                    flex_direction: FlexDirection::Row,
                    align_items: AlignItems::Center,
                    column_gap: Val::Px(8.0),
                    ..Default::default()
                },
                Name::new("PlayerStatsAttackRow"),
            ))
            .with_children(|row| {
                row.spawn((
                    ImageNode::new(sword_icon.clone()),
                    Node {
                        width: Val::Px(PLAYER_STATS_ICON_SIZE),
                        height: Val::Px(PLAYER_STATS_ICON_SIZE),
                        ..Default::default()
                    },
                ));
                row.spawn((
                    PlayerStatsAttackText,
                    Text::new(""),
                    TextFont { font: font.clone(), font_size: PLAYER_STATS_FONT_SIZE, ..Default::default() },
                    TextColor(Color::srgb(0.95, 0.93, 0.9)),
                ));
            });
        // DEF 列同理...
    });

攻擊、防禦欄位不再塞滿符號,而是以「總值 + base + bonus + 倍率」格式呈現。耐力列則簡化為 regen 25.0/s,把當下細節交給上方綠色耐力條呈現。

為了避免一次借用多個 Text 造成 Bevy 的 B0001 借用衝突,更新函式改用 ParamSet

mut text_queries: ParamSet<(
    Query<&mut Text, With<PlayerStatsLevelText>>,
    Query<&mut Text, With<PlayerStatsAttackText>>,
    Query<&mut Text, With<PlayerStatsDefenseText>>,
    Query<&mut Text, With<PlayerStatsStaminaText>>,
)>;

每個欄位輪流 iter_mut().next() 取值,就能在同一幀內安全更新四個 Text


狀態橫幅與除錯輸入清理

控制提示

ui.rsupdate_player_status_text 改成固定顯示按鍵說明,再視狀態追加資訊:

match poison_state {
    Some(_) => {
        *text = Text::new(
            "Space: Attack / Interact | Esc: Pause\nPoisoned: HP -3 per tick",
        );
        color.0 = Color::srgb(0.95, 0.38, 0.32);
    }
    None => {
        *text = Text::new(
            "Space: Attack / Interact | Esc: Pause\nRelease Space to recover stamina",
        );
        color.0 = Color::srgb(0.78, 0.78, 0.72);
    }
}

操作說明以及 UI 更新

玩家進入遊戲就能立刻知道核心操作,中毒時也會看到明顯的提示。

移除除錯熱鍵

  • PlayerPluginplayer_attribute_debug_input_systemplayer_status_debug_shortcuts_system 從 Update 排程移除,遊戲中不再接受 1/2/3/4、Q/W/A/S/R、T/G/Y 的輸入。
  • 對應的系統邏輯全數刪除,連帶把「攻擊 +5」等 log 也換成正式的英文資訊。
  • input_system 保留 Space 與門/傳送門互動,但 log 文字改為 Door interaction event dispatchedAdvancing to level …,整體輸出更一致。

現在的遊戲操作流程完全只面向玩家設計,測試用快捷鍵就不需要了。


小結

整理 UI 還蠻快的,因為一切都是資料驅動。把圖示、字型、提示文字集中在常數與 ECS 節點後,未來要替換應該不會太難。

今日程式碼同步至 repo


上一篇
進度與關卡紀錄系統
系列文
Bevy Rogue-lite 勇者冒險篇 × Rust 遊戲開發筆記26
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言