diff --git a/resources/Ac437_ATT_PC6300.ttf b/resources/Ac437_ATT_PC6300.ttf new file mode 100644 index 0000000..840a431 Binary files /dev/null and b/resources/Ac437_ATT_PC6300.ttf differ diff --git a/resources/cp437.ttf b/resources/cp437.ttf new file mode 100644 index 0000000..db29a29 Binary files /dev/null and b/resources/cp437.ttf differ diff --git a/resources/cp437_8x16.ttf b/resources/cp437_8x16.ttf new file mode 100644 index 0000000..a6b4246 Binary files /dev/null and b/resources/cp437_8x16.ttf differ diff --git a/src/components.rs b/src/components.rs index b489abe..6c51a11 100644 --- a/src/components.rs +++ b/src/components.rs @@ -20,7 +20,7 @@ pub struct SerializationHelper { #[derive(Component, Serialize, Deserialize, Clone)] pub struct DMSerializationHelper { pub map: super::map::MasterDungeonMap, - pub log: Vec>, + pub log: std::collections::BTreeMap>, pub event_counts: HashMap, pub events: HashMap>, } diff --git a/src/consts/mod.rs b/src/consts/mod.rs index dad4214..d21ba60 100644 --- a/src/consts/mod.rs +++ b/src/consts/mod.rs @@ -12,6 +12,6 @@ pub mod prelude { } pub const TILESIZE: f32 = 16.0; -pub const FONTSIZE: f32 = 12.0; +pub const FONTSIZE: f32 = 24.0; pub const DISPLAYWIDTH: u32 = 100; pub const DISPLAYHEIGHT: u32 = 56; diff --git a/src/gamelog/builder.rs b/src/gamelog/builder.rs index 50c9375..69e3aa4 100644 --- a/src/gamelog/builder.rs +++ b/src/gamelog/builder.rs @@ -65,6 +65,7 @@ impl Logger { /// Pushes the finished log entry. pub fn log(self) { - return append_entry(self.fragments); + let key = crate::gamelog::get_event_count(crate::consts::events::EVENT::COUNT_TURN); + return append_entry(key, self.fragments); } } diff --git a/src/gamelog/logstore.rs b/src/gamelog/logstore.rs index 0fdf261..930be62 100644 --- a/src/gamelog/logstore.rs +++ b/src/gamelog/logstore.rs @@ -1,91 +1,60 @@ use super::{ events, LogFragment, Logger }; use bracket_lib::prelude::*; use std::sync::Mutex; +use std::collections::BTreeMap; +use notan::prelude::*; +use notan::text::CreateText; +use crate::consts::{ TILESIZE, FONTSIZE }; lazy_static! { - pub static ref LOG: Mutex>> = Mutex::new(Vec::new()); + pub static ref LOG: Mutex>> = Mutex::new(BTreeMap::new()); } -#[allow(dead_code)] -pub fn append_fragment(fragment: LogFragment) { - LOG.lock().unwrap().push(vec![fragment]); +pub fn render_log(gfx: &mut Graphics, font: ¬an::draw::Font, pos: &(f32, f32), width: f32) { + let mut text = gfx.create_text(); + let log = LOG.lock().unwrap(); + let latest: Vec<_> = log.iter().rev().take(5).collect(); + let mut init = false; + let mut y = pos.1; + for (_, entries) in latest { + let mut written_on_line = false; + for frag in entries.iter() { + if !written_on_line { + text.add(&frag.text) + .font(font) + .position(pos.0, y) + .size(FONTSIZE) + .max_width(width) + .color(Color::from_rgb(frag.colour.r, frag.colour.g, frag.colour.b)) + .v_align_bottom(); + written_on_line = true; + init = true; + } else { + text.chain(&frag.text) + .color(Color::from_rgb(frag.colour.r, frag.colour.g, frag.colour.b)) + .size(FONTSIZE); + } + } + if init { + y = text.last_bounds().min_y(); + } + } + gfx.render(&text); } -pub fn append_entry(fragments: Vec) { - LOG.lock().unwrap().push(fragments); +pub fn append_entry(turn: i32, fragments: Vec) { + let mut log = LOG.lock().unwrap(); + if let Some(existing) = log.get_mut(&turn) { + existing.extend(fragments); + } else { + log.insert(turn, fragments); + } } pub fn clear_log() { LOG.lock().unwrap().clear(); } -pub fn print_log( - console: &mut Box, - pos: Point, - _descending: bool, - len: usize, - maximum_len: i32 -) { - let mut y = pos.y; - let mut x = pos.x; - // Reverse the log, take the number we want to show, and iterate through them - LOG.lock() - .unwrap() - .iter() - .rev() - .take(len) - .for_each(|log| { - let mut entry_len = -2; - // Iterate through each message fragment, and get the total length - // in lines, by adding the length of every fragment and dividing it - // by the maximum length we desire. Then shuffle our start-y by that much. - log.iter().for_each(|frag| { - entry_len += frag.text.len() as i32; - }); - let lines = entry_len / maximum_len; - y -= lines; - let mut i = 0; - log.iter().for_each(|frag| { - // Split every fragment up into single characters. - let parts = frag.text.split(""); - for part in parts { - // This is an extremely hacky solution to a problem I don't understand yet. - // -- without this, the lines *here* and the line count *above* wont match. - if part == "" || part == "\\" { - continue; - } - if i > entry_len { - break; - } - i += 1; - if x + (part.len() as i32) > pos.x + maximum_len { - if y > pos.y - (len as i32) { - console.print(x, y, "-"); - } - y += 1; - x = pos.x; - } - // Stay within bounds - if y > pos.y - (len as i32) { - console.print_color( - x, - y, - frag.colour.into(), - RGB::named(BLACK).into(), - part - ); - } - x += part.len() as i32; - } - }); - // Take away one from the y-axis, because we want to start each entry - // on a new line, and go up an additional amount depending on how many - // lines our *previous* entry took. - y -= 1 + lines; - x = pos.x; - }); -} - pub fn setup_log() { clear_log(); events::clear_events(); @@ -98,11 +67,11 @@ pub fn setup_log() { .log(); } -pub fn clone_log() -> Vec> { +pub fn clone_log() -> BTreeMap> { return LOG.lock().unwrap().clone(); } -pub fn restore_log(log: &mut Vec>) { +pub fn restore_log(log: &mut BTreeMap>) { LOG.lock().unwrap().clear(); LOG.lock().unwrap().append(log); } diff --git a/src/gamelog/mod.rs b/src/gamelog/mod.rs index 0ab110c..5ae498d 100644 --- a/src/gamelog/mod.rs +++ b/src/gamelog/mod.rs @@ -2,7 +2,7 @@ mod builder; pub use builder::*; mod logstore; use logstore::*; -pub use logstore::{ LOG, clear_log, clone_log, print_log, restore_log, setup_log }; +pub use logstore::{ LOG, clear_log, clone_log, render_log, restore_log, setup_log }; mod events; pub use events::*; diff --git a/src/gui/mod.rs b/src/gui/mod.rs index cb773d7..9253a3d 100644 --- a/src/gui/mod.rs +++ b/src/gui/mod.rs @@ -660,13 +660,13 @@ pub fn draw_ui(ecs: &World, ctx: &mut BTerm) { } // Render the message log at [1, 7], ascending, with 7 lines and a max width of 68. - gamelog::print_log( + /*gamelog::print_log( &mut BACKEND_INTERNAL.lock().consoles[TEXT_LAYER].console, Point::new(1 * TEXT_FONT_MOD, 7), false, 7, (VIEWPORT_W - 1) * TEXT_FONT_MOD - ); + );*/ // Render id let map = ecs.fetch::(); diff --git a/src/main.rs b/src/main.rs index ff896d5..2b9bbde 100644 --- a/src/main.rs +++ b/src/main.rs @@ -33,7 +33,7 @@ fn setup(gfx: &mut Graphics) -> State { .unwrap(); let data = include_bytes!("../resources/td.json"); let atlas = create_textures_from_atlas(data, &texture).unwrap(); - let font = gfx.create_font(include_bytes!("../resources/PressStart2P-Regular.ttf")).unwrap(); + let font = gfx.create_font(include_bytes!("../resources/Ac437_ATT_PC6300.ttf")).unwrap(); let mut gs = State { ecs: World::new(), base_texture: texture, @@ -253,26 +253,32 @@ fn draw_camera( } // TODO: Use sprites here, not text drawing. Put bitmap font into atlas. let renderable = renderables.get(entry.1.e).unwrap(); - draw.text(&font, &format!("{}", renderable.glyph as u8 as char)) + draw.text( + &font, + &format!("{}", bracket_lib::terminal::to_char(renderable.glyph as u8)) + ) .position( ((entry.0.x as f32) + 0.5) * TILESIZE, ((entry.0.y as f32) + 0.5) * TILESIZE ) .color(Color::from_rgb(renderable.fg.r, renderable.fg.g, renderable.fg.b)) - .size(FONTSIZE + 2.0) + .size(FONTSIZE) .h_align_center() .v_align_middle(); // Draw entity } DrawType::VisibleAndRemember => { let renderable = renderables.get(entry.1.e).unwrap(); - draw.text(&font, &format!("{}", renderable.glyph as u8 as char)) + draw.text( + &font, + &format!("{}", bracket_lib::terminal::to_char(renderable.glyph as u8)) + ) .position( ((entry.0.x as f32) + 0.5) * TILESIZE, ((entry.0.y as f32) + 0.5) * TILESIZE ) .color(Color::from_rgb(renderable.fg.r, renderable.fg.g, renderable.fg.b)) - .size(FONTSIZE + 2.0) + .size(FONTSIZE) .h_align_center() .v_align_middle(); // TODO: Update map memory. @@ -434,13 +440,14 @@ fn draw_bg(_ecs: &World, draw: &mut Draw, atlas: &HashMap) { fn draw(app: &mut App, gfx: &mut Graphics, gs: &mut State) { let mut draw = gfx.create_draw(); draw.clear(Color::BLACK); + let mut log = false; match *gs.ecs.fetch::() { | RunState::MainMenu { .. } | RunState::CharacterCreation { .. } | RunState::PreRun { .. } => {} RunState::MapGeneration => { draw_bg(&gs.ecs, &mut draw, &gs.atlas); - if config::CONFIG.logging.show_mapgen { + if config::CONFIG.logging.show_mapgen && gs.mapgen_history.len() > 0 { render_map_in_view( &gs.mapgen_history[gs.mapgen_index], &gs.ecs, @@ -454,7 +461,7 @@ fn draw(app: &mut App, gfx: &mut Graphics, gs: &mut State) { draw_bg(&gs.ecs, &mut draw, &gs.atlas); draw_camera(&gs.ecs, &mut draw, &gs.atlas, &gs.font); gui::draw_ui2(&gs.ecs, &mut draw, &gs.atlas, &gs.font); - //print_log(&mut draw, &gs.font, Point::new(1, 7), false, 7, VIEWPORT_W + 22); + log = true; } } match *gs.ecs.fetch::() { @@ -474,7 +481,14 @@ fn draw(app: &mut App, gfx: &mut Graphics, gs: &mut State) { _ => {} } gfx.render(&draw); - write(gfx, &gs.font, &(TILESIZE, TILESIZE * 8.0), true); + if log { + gamelog::render_log( + gfx, + &gs.font, + &(TILESIZE, TILESIZE * 8.0 + 4.0), + (VIEWPORT_W as f32) * TILESIZE + ); + } } fn idx_to_px(idx: usize, map: &Map) -> (f32, f32) { @@ -487,138 +501,3 @@ fn idx_to_px(idx: usize, map: &Map) -> (f32, f32) { fn update(ctx: &mut App, state: &mut State) { state.update(ctx); } - -pub fn print_log( - draw: &mut notan::draw::Draw, - font: ¬an::draw::Font, - pos: Point, - _descending: bool, - len: usize, - maximum_len: i32 -) { - let mut y = pos.y; - let mut x = pos.x; - let mut x_px = (x as f32) * TILESIZE; - // Reverse the log, take the number we want to show, and iterate through them - gamelog::LOG - .lock() - .unwrap() - .iter() - .rev() - .take(len) - .for_each(|log| { - let mut entry_len = -2; - // Iterate through each message fragment, and get the total length - // in lines, by adding the length of every fragment and dividing it - // by the maximum length we desire. Then shuffle our start-y by that much. - log.iter().for_each(|frag| { - entry_len += frag.text.len() as i32; - }); - let lines = entry_len / maximum_len; - y -= lines; - let mut i = 0; - log.iter().for_each(|frag| { - // Split every fragment up into single characters. - let parts = frag.text.split(""); - for part in parts { - // This is an extremely hacky solution to a problem I don't understand yet. - // -- without this, the lines *here* and the line count *above* wont match. - if part == "" || part == "\\" { - continue; - } - if i > entry_len { - break; - } - i += 1; - if x + (part.len() as i32) > pos.x + maximum_len { - if y > pos.y - (len as i32) { - draw.text(&font, "-") - .position(x_px, (y as f32) * TILESIZE) - .size(FONTSIZE); - } - y += 1; - x = pos.x; - x_px = (x as f32) * TILESIZE; - } - // Stay within bounds - if y > pos.y - (len as i32) { - draw.text(&font, part) - .position(x_px, (y as f32) * TILESIZE) - .size(FONTSIZE) - .color(Color::from_rgb(frag.colour.r, frag.colour.g, frag.colour.b)); - } - x += part.len() as i32; - x_px = draw.last_text_bounds().max_x(); - } - }); - // Take away one from the y-axis, because we want to start each entry - // on a new line, and go up an additional amount depending on how many - // lines our *previous* entry took. - y -= 1 + lines; - x = pos.x; - x_px = (x as f32) * TILESIZE; - }); -} - -use std::collections::BTreeMap; -fn write(gfx: &mut Graphics, font: ¬an::draw::Font, pos: &(f32, f32), desc: bool) { - use notan::text::CreateText; - let mut text = gfx.create_text(); - let log = get_log(); - let latest: Vec<_> = log.iter().rev().take(4).rev().collect(); - let mut initial = true; - for (_, entries) in latest { - let mut wrote = false; - for (message, colour) in entries.iter() { - if initial { - if desc { - text.add(&message) - .font(font) - .position(pos.0, pos.1) - .size(FONTSIZE) - .max_width((VIEWPORT_W as f32) * TILESIZE) - .color(*colour) - .v_align_bottom(); - } else { - text.add(&message) - .font(font) - .position(pos.0, pos.1) - .size(FONTSIZE) - .max_width((VIEWPORT_W as f32) * TILESIZE) - .color(*colour); - } - initial = false; - } else { - text.chain(&message).color(*colour).size(FONTSIZE); - } - wrote = true; - } - if wrote { - text.chain("\n"); - } - } - gfx.render(&text); -} - -fn get_log() -> BTreeMap> { - let mut log: BTreeMap> = BTreeMap::new(); - log.entry(4).or_insert_with(Vec::new).push(("This is a".to_string(), Color::WHITE)); - log.entry(4).or_insert_with(Vec::new).push((" test".to_string(), Color::RED)); - log.entry(5).or_insert_with(Vec::new).push(("This is the fifth".to_string(), Color::WHITE)); - log.entry(5).or_insert_with(Vec::new).push((" test".to_string(), Color::BLUE)); - log.entry(6).or_insert_with(Vec::new).push(("This is the sixth".to_string(), Color::WHITE)); - log.entry(6).or_insert_with(Vec::new).push((" test".to_string(), Color::BLUE)); - log.entry(7).or_insert_with(Vec::new).push(("This is the seventh".to_string(), Color::WHITE)); - log.entry(7).or_insert_with(Vec::new).push((" test".to_string(), Color::BLUE)); - log.entry(8).or_insert_with(Vec::new).push(("This is the eighth".to_string(), Color::WHITE)); - log.entry(8) - .or_insert_with(Vec::new) - .push(( - " test with a very long message, so that I can test the line wrapping.".to_string(), - Color::BLUE, - )); - log.entry(9).or_insert_with(Vec::new).push(("This is the ninth".to_string(), Color::WHITE)); - log.entry(9).or_insert_with(Vec::new).push((" test".to_string(), Color::BLUE)); - - log -}