fix: bigger UI panels with more spacing between text lines
Character panel: - Width 44 -> 52, height 44 -> 62 - Text rows spaced 8 apart (was 6) — no more squished text - HP/XP bars 38 wide (was 32) - Stats with double space between pairs - Inventory section at bottom with more room HUD bar: - Height 18 -> 28 - Rows at y_top+2, +12, +22 (was +1, +7, +13) Inventory overlay: - Slots 12x10 (was 8x6), gap 3 (was 2) - Panel auto-sizes larger - Click hitboxes in main.rs updated to match Fixed depth_shown_in_hud test for new HUD height. All 171 tests + 14 scenarios pass.
This commit is contained in:
+10
-10
@@ -369,11 +369,11 @@ fn run_gpu_mode<R: GpuRenderer>(title: &str) {
|
||||
|
||||
let cols = 4i32;
|
||||
let rows = 2i32;
|
||||
let slot_w = 8i32;
|
||||
let slot_h = 6i32;
|
||||
let gap = 2i32;
|
||||
let slot_w = 12i32;
|
||||
let slot_h = 10i32;
|
||||
let gap = 3i32;
|
||||
let panel_w = cols * slot_w + (cols + 1) * gap + 4;
|
||||
let panel_h = rows * slot_h + (rows + 1) * gap + 20;
|
||||
let panel_h = rows * slot_h + (rows + 1) * gap + 28;
|
||||
let px_start = (ui_w - panel_w) / 2;
|
||||
let py_start = (ui_h - panel_h) / 2;
|
||||
|
||||
@@ -381,7 +381,7 @@ fn run_gpu_mode<R: GpuRenderer>(title: &str) {
|
||||
for col in 0..cols {
|
||||
let idx = (row * cols + col) as usize;
|
||||
let sx = px_start + gap + col * (slot_w + gap) + 2;
|
||||
let sy = py_start + 10 + row * (slot_h + gap) + gap;
|
||||
let sy = py_start + 14 + row * (slot_h + gap) + gap;
|
||||
if mouse_ui_x >= sx
|
||||
&& mouse_ui_x < sx + slot_w
|
||||
&& mouse_ui_y >= sy
|
||||
@@ -404,11 +404,11 @@ fn run_gpu_mode<R: GpuRenderer>(title: &str) {
|
||||
|
||||
let cols = 4i32;
|
||||
let rows = 2i32;
|
||||
let slot_w = 8i32;
|
||||
let slot_h = 6i32;
|
||||
let gap = 2i32;
|
||||
let slot_w = 12i32;
|
||||
let slot_h = 10i32;
|
||||
let gap = 3i32;
|
||||
let panel_w = cols * slot_w + (cols + 1) * gap + 4;
|
||||
let panel_h = rows * slot_h + (rows + 1) * gap + 20;
|
||||
let panel_h = rows * slot_h + (rows + 1) * gap + 28;
|
||||
let px_start = (ui_w - panel_w) / 2;
|
||||
let py_start = (ui_h - panel_h) / 2;
|
||||
|
||||
@@ -416,7 +416,7 @@ fn run_gpu_mode<R: GpuRenderer>(title: &str) {
|
||||
for col in 0..cols {
|
||||
let idx = (row * cols + col) as usize;
|
||||
let sx = px_start + gap + col * (slot_w + gap) + 2;
|
||||
let sy = py_start + 10 + row * (slot_h + gap) + gap;
|
||||
let sy = py_start + 14 + row * (slot_h + gap) + gap;
|
||||
if mouse_ui_x >= sx
|
||||
&& mouse_ui_x < sx + slot_w
|
||||
&& mouse_ui_y >= sy
|
||||
|
||||
+37
-34
@@ -334,8 +334,8 @@ impl UiLayer {
|
||||
player: Option<&Entity>,
|
||||
player_state: &crate::entity::player::Player,
|
||||
) {
|
||||
let w = 44i32;
|
||||
let h = 44i32;
|
||||
let w = 52i32;
|
||||
let h = 62i32;
|
||||
let bg = [22u8, 26, 38];
|
||||
let border = [160u8, 180, 255];
|
||||
let title = [220u8, 230, 255];
|
||||
@@ -375,11 +375,11 @@ impl UiLayer {
|
||||
|
||||
let title_text = "STATUS";
|
||||
let tx = start_x + (w - Self::text_width(title_text)) / 2;
|
||||
self.draw_text(tx, start_y + 1, title_text, title, 255);
|
||||
self.draw_text(tx, start_y + 2, title_text, title, 255);
|
||||
|
||||
if let Some(p) = player {
|
||||
let hp_ratio = (p.health / p.max_health).clamp(0.0, 1.0);
|
||||
let hp_filled = (hp_ratio * 32.0).round() as i32;
|
||||
let hp_filled = (hp_ratio * 38.0).round() as i32;
|
||||
let bar_color = if hp_ratio > 0.6 {
|
||||
[80, 240, 80]
|
||||
} else if hp_ratio > 0.3 {
|
||||
@@ -387,56 +387,59 @@ impl UiLayer {
|
||||
} else {
|
||||
[255, 60, 60]
|
||||
};
|
||||
self.draw_text(start_x + 2, start_y + 7, "HP", fg, 255);
|
||||
for i in 0..32 {
|
||||
self.draw_text(start_x + 3, start_y + 10, "HP", fg, 255);
|
||||
for i in 0..38 {
|
||||
let ch = if i < hp_filled { '#' } else { '-' };
|
||||
let c = if i < hp_filled {
|
||||
bar_color
|
||||
} else {
|
||||
[80, 80, 100]
|
||||
};
|
||||
self.set(start_x + 10 + i, start_y + 7, ch, c, bg);
|
||||
self.set(start_x + 10 + i, start_y + 10, ch, c, bg);
|
||||
}
|
||||
let hp_text = format!("{}/{} LV:{}", p.health as i32, p.max_health as i32, p.level);
|
||||
self.draw_text(start_x + 2, start_y + 13, &hp_text, fg, 255);
|
||||
let hp_text = format!(
|
||||
"{}/{} LV:{}",
|
||||
p.health as i32, p.max_health as i32, p.level
|
||||
);
|
||||
self.draw_text(start_x + 3, start_y + 18, &hp_text, fg, 255);
|
||||
|
||||
let xp_ratio = (p.xp as f32 / p.xp_to_level() as f32).clamp(0.0, 1.0);
|
||||
let xp_filled = (xp_ratio * 32.0).round() as i32;
|
||||
self.draw_text(start_x + 2, start_y + 19, "XP", fg, 255);
|
||||
for i in 0..32 {
|
||||
let xp_filled = (xp_ratio * 38.0).round() as i32;
|
||||
self.draw_text(start_x + 3, start_y + 26, "XP", fg, 255);
|
||||
for i in 0..38 {
|
||||
let ch = if i < xp_filled { '#' } else { '-' };
|
||||
let c = if i < xp_filled {
|
||||
[80, 160, 240]
|
||||
} else {
|
||||
[60, 60, 80]
|
||||
};
|
||||
self.set(start_x + 10 + i, start_y + 19, ch, c, bg);
|
||||
self.set(start_x + 10 + i, start_y + 26, ch, c, bg);
|
||||
}
|
||||
|
||||
let stats = format!("STR:{} AGI:{}", p.strength, p.agility);
|
||||
self.draw_text(start_x + 2, start_y + 25, &stats, dim, 255);
|
||||
let stats2 = format!("TOU:{} WIL:{}", p.toughness, p.willpower);
|
||||
self.draw_text(start_x + 2, start_y + 31, &stats2, dim, 255);
|
||||
let stats = format!("STR:{} AGI:{}", p.strength, p.agility);
|
||||
self.draw_text(start_x + 3, start_y + 36, &stats, dim, 255);
|
||||
let stats2 = format!("TOU:{} WIL:{}", p.toughness, p.willpower);
|
||||
self.draw_text(start_x + 3, start_y + 44, &stats2, dim, 255);
|
||||
}
|
||||
|
||||
let inv_title = "INV:";
|
||||
self.draw_text(start_x + 2, start_y + 37, inv_title, fg, 255);
|
||||
let mut ix = start_x + 14;
|
||||
let inv_title = "INVENTORY";
|
||||
self.draw_text(start_x + 3, start_y + 52, inv_title, fg, 255);
|
||||
let mut ix = start_x + 3;
|
||||
for item in player_state.inventory.iter().take(8) {
|
||||
if ix + 1 >= start_x + w - 1 {
|
||||
if ix + 2 >= start_x + w - 2 {
|
||||
break;
|
||||
}
|
||||
let [ch1, ch2] = item.display_glyph();
|
||||
let col = item.color();
|
||||
self.set(ix, start_y + 38, ch1, col, bg);
|
||||
self.set(ix, start_y + 58, ch1, col, bg);
|
||||
self.set(
|
||||
ix + 1,
|
||||
start_y + 38,
|
||||
start_y + 58,
|
||||
ch2,
|
||||
[col[0] / 2, col[1] / 2, col[2] / 2],
|
||||
bg,
|
||||
);
|
||||
ix += 3;
|
||||
ix += 4;
|
||||
}
|
||||
|
||||
let status = if let Some(p) = player {
|
||||
@@ -482,11 +485,11 @@ impl UiLayer {
|
||||
|
||||
let cols = 4i32;
|
||||
let rows = 2i32;
|
||||
let slot_w = 8i32;
|
||||
let slot_h = 6i32;
|
||||
let gap = 2i32;
|
||||
let slot_w = 12i32;
|
||||
let slot_h = 10i32;
|
||||
let gap = 3i32;
|
||||
let panel_w = cols * slot_w + (cols + 1) * gap + 4;
|
||||
let panel_h = rows * slot_h + (rows + 1) * gap + 20;
|
||||
let panel_h = rows * slot_h + (rows + 1) * gap + 28;
|
||||
|
||||
let px_start = (screen_w as i32 - panel_w) / 2;
|
||||
let py_start = (screen_h as i32 - panel_h) / 2;
|
||||
@@ -538,7 +541,7 @@ impl UiLayer {
|
||||
for col in 0..cols {
|
||||
let idx = (row * cols + col) as usize;
|
||||
let sx = px_start + gap + col * (slot_w + gap) + 2;
|
||||
let sy = py_start + 10 + row * (slot_h + gap) + gap;
|
||||
let sy = py_start + 14 + row * (slot_h + gap) + gap;
|
||||
|
||||
for y in 0..slot_h {
|
||||
for x in 0..slot_w {
|
||||
@@ -569,7 +572,7 @@ impl UiLayer {
|
||||
let [ch1, ch2] = item.display_glyph();
|
||||
let col = item.color();
|
||||
let cx = sx + slot_w / 2 - 1;
|
||||
let cy = sy + slot_h / 2 - 1;
|
||||
let cy = sy + slot_h / 2 - 2;
|
||||
self.set(cx, cy, ch1, col, slot_bg);
|
||||
self.set(
|
||||
cx + 1,
|
||||
@@ -683,11 +686,11 @@ impl UiLayer {
|
||||
.map(|i| i.display_string())
|
||||
.unwrap_or(" ".to_string());
|
||||
|
||||
let bar_h = 18i32;
|
||||
let bar_h = 28i32;
|
||||
let y_top = screen_h as i32 - bar_h;
|
||||
let y_row1 = y_top + 1;
|
||||
let y_row2 = y_top + 7;
|
||||
let y_row3 = y_top + 13;
|
||||
let y_row1 = y_top + 2;
|
||||
let y_row2 = y_top + 12;
|
||||
let y_row3 = y_top + 22;
|
||||
|
||||
for row in y_top..screen_h as i32 {
|
||||
for x in 0..screen_w {
|
||||
|
||||
+8
-5
@@ -51,9 +51,11 @@ fn depth_shown_in_hud() {
|
||||
let s = setup();
|
||||
let player = s.game.entities.all()[0].clone();
|
||||
let mut ui = verbatim::ui::UiLayer::new();
|
||||
let screen_w = 320;
|
||||
let screen_h = 100;
|
||||
ui.draw_hud(
|
||||
80,
|
||||
25,
|
||||
screen_w,
|
||||
screen_h,
|
||||
Some(&player),
|
||||
s.game.tick,
|
||||
verbatim::world::cell::MaterialId::Sand,
|
||||
@@ -68,10 +70,11 @@ fn depth_shown_in_hud() {
|
||||
player.level, player.xp, 0, 0, s.game.depth, s.game.tick
|
||||
);
|
||||
let stats_w = verbatim::ui::UiLayer::text_width(&stats);
|
||||
let stats_x = (80 - stats_w).max(0);
|
||||
let line: String = (stats_x..80)
|
||||
let stats_x = (screen_w as i32 - stats_w as i32).max(0);
|
||||
let y_row3 = screen_h as i32 - 28 + 22;
|
||||
let line: String = (stats_x as i32..screen_w as i32)
|
||||
.step_by(3)
|
||||
.map(|x| ui.get(x, 24).map(|c| c.ch).unwrap_or(' '))
|
||||
.map(|x| ui.get(x, y_row3).map(|c| c.ch).unwrap_or(' '))
|
||||
.collect();
|
||||
assert!(line.contains("D:1"), "HUD should show depth: {}", line);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user