diff --git a/resources/terminal8x8.png b/resources/terminal8x8.png new file mode 100644 index 0000000..4e40554 Binary files /dev/null and b/resources/terminal8x8.png differ diff --git a/src/components.rs b/src/components.rs index 317c01b..bc9fdf0 100644 --- a/src/components.rs +++ b/src/components.rs @@ -20,3 +20,12 @@ pub struct WantsToMove { pub entity: Entity, pub destination: Point, } + +#[derive(Clone, Copy, Debug, PartialEq)] +pub struct Health { + pub current: i32, + pub max: i32, +} + +#[derive(Clone, PartialEq)] +pub struct Name(pub String); diff --git a/src/main.rs b/src/main.rs index 7f0aa7a..093c305 100644 --- a/src/main.rs +++ b/src/main.rs @@ -65,7 +65,11 @@ impl GameState for State { ctx.cls(); ctx.set_active_console(1); ctx.cls(); + ctx.set_active_console(2); + ctx.cls(); self.resources.insert(ctx.key); + ctx.set_active_console(0); + self.resources.insert(Point::from_tuple(ctx.mouse_pos())); //self.systems.execute(&mut self.ecs, &mut self.resources); let current_state = self.resources.get::().unwrap().clone(); match current_state { @@ -91,8 +95,10 @@ fn main() -> BError { .with_tile_dimensions(32, 32) .with_resource_path("resources/") .with_font("dungeonfont.png", 32, 32) + .with_font("terminal8x8.png", 8, 8) .with_simple_console(DISPLAY_WIDTH, DISPLAY_HEIGHT, "dungeonfont.png") .with_simple_console_no_bg(DISPLAY_WIDTH, DISPLAY_HEIGHT, "dungeonfont.png") + .with_simple_console_no_bg(SCREEN_WIDTH * 2, SCREEN_HEIGHT * 2, "terminal8x8.png") .build()?; main_loop(context, State::new()) } diff --git a/src/map_builder.rs b/src/map_builder.rs index 14e31f8..df1c1d4 100644 --- a/src/map_builder.rs +++ b/src/map_builder.rs @@ -1,6 +1,6 @@ use crate::prelude::*; -const NUM_ROOMS: usize = 20; +const NUM_ROOMS: usize = 20; pub struct MapBuilder { pub map: Map, pub rooms: Vec, @@ -80,10 +80,10 @@ impl MapBuilder { if rng.range(0, 2) == 1 { self.apply_horizontal_tunnel(prev.x, new.x, prev.y); - self.apply_vertical_tunnel(prev.y, new.y, prev.x); + self.apply_vertical_tunnel(prev.y, new.y, new.x); } else { self.apply_vertical_tunnel(prev.y, new.y, prev.x); - self.apply_horizontal_tunnel(prev.x, new.x, prev.y); + self.apply_horizontal_tunnel(prev.x, new.x, new.y); } } } diff --git a/src/spawners.rs b/src/spawners.rs index 52753f6..8da6bd3 100644 --- a/src/spawners.rs +++ b/src/spawners.rs @@ -8,22 +8,38 @@ pub fn spawn_player(ecs: &mut World, pos: Point) { color: ColorPair::new(WHITE, BLACK), glyph: to_cp437('@'), }, + Health { + current: 20, + max: 20, + }, )); } pub fn spawn_monster(ecs: &mut World, rng: &mut RandomNumberGenerator, pos: Point) { + let (hp, name, glyph) = match rng.roll_dice(1, 10) { + 1..=8 => goblin(), + _ => orc(), + }; + ecs.push(( Enemy, pos, Render { color: ColorPair::new(WHITE, BLACK), - glyph: match rng.range(0, 4) { - 0 => to_cp437('E'), // Ettin - 1 => to_cp437('O'), // Ogre - 2 => to_cp437('o'), // Orc - _ => to_cp437('g'), // goblin - }, + glyph, }, MovingRandomly {}, + Health { + current: hp, + max: hp, + }, + Name(name), )); } + +fn goblin() -> (i32, String, FontCharType) { + (1, "Goblin".to_string(), to_cp437('g')) +} +fn orc() -> (i32, String, FontCharType) { + (2, "orc".to_string(), to_cp437('o')) +} diff --git a/src/systems/hud.rs b/src/systems/hud.rs new file mode 100644 index 0000000..b64fa1f --- /dev/null +++ b/src/systems/hud.rs @@ -0,0 +1,26 @@ +use crate::prelude::*; + +#[system] +#[read_component(Health)] +#[read_component(Player)] +pub fn hud(ecs: &SubWorld) { + let mut health_query = <&Health>::query().filter(component::()); + let player_health = health_query.iter(ecs).nth(0).unwrap(); + + let mut draw_batch = DrawBatch::new(); + draw_batch.target(2); + draw_batch.print_centered(1, "Explore the Dungeon. Cursor keys to move."); + draw_batch.bar_horizontal( + Point::zero(), + SCREEN_WIDTH * 2, + player_health.current, + player_health.max, + ColorPair::new(RED, BLACK), + ); + draw_batch.print_color_centered( + 0, + format!(" Health: {}/{} ", player_health.current, player_health.max,), + ColorPair::new(WHITE, RED), + ); + draw_batch.submit(10000).expect("Batch Error"); +} diff --git a/src/systems/mod.rs b/src/systems/mod.rs index e34db46..4542f1b 100644 --- a/src/systems/mod.rs +++ b/src/systems/mod.rs @@ -2,10 +2,12 @@ use crate::prelude::*; mod collisions; mod end_turn; mod entity_render; +mod hud; mod map_render; mod movement; mod player_input; mod random_move; +mod tooltips; pub fn input_build_scheduler() -> Schedule { Schedule::builder() @@ -13,6 +15,8 @@ pub fn input_build_scheduler() -> Schedule { .flush() .add_system(map_render::map_render_system()) .add_system(entity_render::entity_render_system()) + .add_system(hud::hud_system()) + .add_system(tooltips::tooltips_system()) .build() } pub fn player_build_scheduler() -> Schedule { @@ -23,6 +27,7 @@ pub fn player_build_scheduler() -> Schedule { .flush() .add_system(map_render::map_render_system()) .add_system(entity_render::entity_render_system()) + .add_system(hud::hud_system()) .add_system(end_turn::end_turn_system()) .build() } @@ -36,6 +41,7 @@ pub fn monster_build_scheduler() -> Schedule { .flush() .add_system(map_render::map_render_system()) .add_system(entity_render::entity_render_system()) + .add_system(hud::hud_system()) .add_system(end_turn::end_turn_system()) .build() } diff --git a/src/systems/tooltips.rs b/src/systems/tooltips.rs new file mode 100644 index 0000000..93d85e3 --- /dev/null +++ b/src/systems/tooltips.rs @@ -0,0 +1,35 @@ +use crate::prelude::*; + +#[system] +#[read_component(Point)] +#[read_component(Name)] +#[read_component(Health)] +pub fn tooltips( + ecs: &SubWorld, + #[resource] mouse_pos: &Point, // (1) + #[resource] camera: &Camera, // (2) +) { + let mut positions = <(Entity, &Point, &Name)>::query(); // (3) + let offset = Point::new(camera.left_x, camera.top_y); + let map_pos = *mouse_pos + offset; // (4) + let mut draw_batch = DrawBatch::new(); + draw_batch.target(2); + positions + .iter(ecs) + .filter(|(_, pos, _)| **pos == map_pos) // (5) + .for_each(|(entity, _, name)| { + let screen_pos = *mouse_pos * 4; // (6) + let display = if let Ok(health) = ecs + .entry_ref(*entity) // (7) + .unwrap() + .get_component::() + { + format!("{} : {} hp", &name.0, health.current) // (8) + } else { + // (9) + name.0.clone() + }; + draw_batch.print(screen_pos, &display); + }); + draw_batch.submit(10100).expect("Batch error"); +}