diff --git a/benchmark_results.json b/benchmark_results.json index 619b50b..ae215ca 100644 --- a/benchmark_results.json +++ b/benchmark_results.json @@ -1,17 +1,17 @@ { "mode": "graphics", "ticks": 300, - "total_time_ms": 4845.5, - "avg_fps": 61.9, - "avg_frame_time_ms": 16.12, - "p99_frame_time_ms": 145.95, - "min_frame_time_ms": 8.19, + "total_time_ms": 3153.2, + "avg_fps": 95.1, + "avg_frame_time_ms": 10.48, + "p99_frame_time_ms": 65.20, + "min_frame_time_ms": 6.55, "subsystems": { - "ca_step_avg_us": 8153, - "ca_step_p99_us": 137703, - "ca_step_min_us": 1174, - "render_avg_us": 4433, - "render_p99_us": 6450, - "render_min_us": 3956 + "ca_step_avg_us": 3386, + "ca_step_p99_us": 58075, + "ca_step_min_us": 231, + "render_avg_us": 3770, + "render_p99_us": 5334, + "render_min_us": 3320 } } \ No newline at end of file diff --git a/noita-reference1.png b/noita-reference1.png new file mode 100644 index 0000000..21e17ae Binary files /dev/null and b/noita-reference1.png differ diff --git a/noita-reference2.png b/noita-reference2.png new file mode 100644 index 0000000..8e45f55 Binary files /dev/null and b/noita-reference2.png differ diff --git a/src/game.rs b/src/game.rs index d47f483..9ffd91d 100644 --- a/src/game.rs +++ b/src/game.rs @@ -357,6 +357,7 @@ impl Game { let ui_h = (vh as i32) * crate::ui::UI_SCALE; let fs = ((ui_h / 200).max(2)).min(6) as i32; self.ui.set_font_scale(fs); + self.ui.resize(ui_w as usize, ui_h as usize); let player = self.player.entity(&self.entities).cloned(); let brush = self diff --git a/src/ui/mod.rs b/src/ui/mod.rs index 0131eb5..52ca944 100644 --- a/src/ui/mod.rs +++ b/src/ui/mod.rs @@ -1,5 +1,3 @@ -use std::collections::HashMap; - use crate::entity::entity::{Entity, EntityKind}; use crate::world::cell::MaterialId; use crate::world::chunked_grid::ChunkedGrid; @@ -17,7 +15,10 @@ pub struct UiCell { } pub struct UiLayer { - cells: HashMap<(i32, i32), UiCell>, + cells: Vec>, + width: usize, + height: usize, + dirty_keys: Vec<(i32, i32)>, messages: Vec<(String, u32)>, damage_numbers: Vec, font_scale: i32, @@ -35,7 +36,10 @@ pub struct DamageNumber { impl UiLayer { pub fn new() -> Self { Self { - cells: HashMap::new(), + cells: Vec::new(), + width: 0, + height: 0, + dirty_keys: Vec::new(), messages: Vec::new(), damage_numbers: Vec::new(), font_scale: 2, @@ -61,7 +65,10 @@ impl UiLayer { } pub fn clear(&mut self) { - self.cells.clear(); + for c in self.cells.iter_mut() { + *c = None; + } + self.dirty_keys.clear(); self.damage_numbers.retain(|d| d.life > 0); for d in &mut self.damage_numbers { d.y -= 0.1; @@ -69,28 +76,53 @@ impl UiLayer { } } + pub fn resize(&mut self, w: usize, h: usize) { + self.width = w; + self.height = h; + self.cells.clear(); + self.cells.resize(w * h, None); + self.dirty_keys.clear(); + } + + #[inline] + fn idx(&self, x: i32, y: i32) -> Option { + if x < 0 || y < 0 || x as usize >= self.width || y as usize >= self.height { + return None; + } + Some(y as usize * self.width + x as usize) + } + pub fn set(&mut self, x: i32, y: i32, ch: char, fg: [u8; 3], bg: [u8; 3]) { - self.cells.insert( - (x, y), - UiCell { + if let Some(i) = self.idx(x, y) { + let was_none = self.cells[i].is_none(); + self.cells[i] = Some(UiCell { ch, fg, bg, alpha: 255, - }, - ); + }); + if was_none { + self.dirty_keys.push((x, y)); + } + } } pub fn set_alpha(&mut self, x: i32, y: i32, ch: char, fg: [u8; 3], bg: [u8; 3], alpha: u8) { - self.cells.insert((x, y), UiCell { ch, fg, bg, alpha }); + if let Some(i) = self.idx(x, y) { + let was_none = self.cells[i].is_none(); + self.cells[i] = Some(UiCell { ch, fg, bg, alpha }); + if was_none { + self.dirty_keys.push((x, y)); + } + } } pub fn get(&self, x: i32, y: i32) -> Option<&UiCell> { - self.cells.get(&(x, y)) + self.idx(x, y).and_then(|i| self.cells[i].as_ref()) } pub fn keys(&self) -> impl Iterator { - self.cells.keys() + self.dirty_keys.iter() } pub fn add_message(&mut self, text: &str) { diff --git a/tests/descent.rs b/tests/descent.rs index dde4f90..48b3539 100644 --- a/tests/descent.rs +++ b/tests/descent.rs @@ -53,6 +53,7 @@ fn depth_shown_in_hud() { let mut ui = verbatim::ui::UiLayer::new(); let screen_w = 320; let screen_h = 100; + ui.resize(screen_w, screen_h); ui.draw_hud( screen_w, screen_h, diff --git a/tests/projectiles.rs b/tests/projectiles.rs index ddf9a33..6bd5313 100644 --- a/tests/projectiles.rs +++ b/tests/projectiles.rs @@ -172,6 +172,7 @@ fn ui_hud_shows_player_hp() { let mut s = setup(); let mut ui = verbatim::ui::UiLayer::new(); let player = s.game.entities.all()[0].clone(); + ui.resize(80, 25); ui.draw_hud( 80, 25,