From e8aa7494a41351b89c34fb522252e6aefc4ae31f Mon Sep 17 00:00:00 2001 From: Llywelwyn Date: Sun, 24 Sep 2023 16:55:47 +0100 Subject: [PATCH] fixing the sea of red - entity rendering for things in view --- src/camera.rs | 51 +++++++++++++++++++++++------------- src/gui/farlook.rs | 21 +++++---------- src/gui/identify_menu.rs | 8 +++--- src/gui/mod.rs | 46 ++++++++++++++++++-------------- src/gui/remove_curse_menu.rs | 8 +++--- src/gui/tooltip.rs | 6 ++--- src/main.rs | 51 ++++++++++++++++++++++-------------- src/player.rs | 7 +++-- src/states/state.rs | 11 ++++---- 9 files changed, 120 insertions(+), 89 deletions(-) diff --git a/src/camera.rs b/src/camera.rs index 61b1ebc..09ff97b 100644 --- a/src/camera.rs +++ b/src/camera.rs @@ -7,8 +7,13 @@ use super::data::prelude::*; const SHOW_BOUNDARIES: bool = false; -pub fn get_offset() -> (i32, i32) { - return (1, 10); +pub struct Offsets { + pub x: i32, + pub y: i32, +} + +pub fn get_offset() -> Offsets { + return Offsets { x: 1, y: 10 }; } pub struct ScreenBounds { @@ -52,13 +57,13 @@ pub fn in_bounds(x: i32, y: i32, min_x: i32, min_y: i32, upper_x: i32, upper_y: pub fn render_camera(ecs: &World, ctx: &mut BTerm) { let map = ecs.fetch::(); - let (min_x, max_x, min_y, max_y, x_offset, y_offset) = get_screen_bounds(ecs); + let bounds = get_screen_bounds(ecs); // Render map let mut y = 0; - for t_y in min_y..max_y { + for t_y in bounds.min_y..bounds.max_y { let mut x = 0; - for t_x in min_x..max_x { + for t_x in bounds.min_x..bounds.max_x { if t_x >= 0 && t_x < map.width && t_y >= 0 && t_y < map.height { let idx = map.xy_idx(t_x, t_y); if map.revealed_tiles[idx] { @@ -69,7 +74,7 @@ pub fn render_camera(ecs: &World, ctx: &mut BTerm) { Some(*ecs.fetch::()), None ); - ctx.set(x + x_offset, y + y_offset, fg, bg, glyph); + ctx.set(x + bounds.x_offset, y + bounds.y_offset, fg, bg, glyph); } else { ctx.set_active_console(0); let (id, tint) = crate::map::themes::get_sprite_for_id( @@ -78,7 +83,12 @@ pub fn render_camera(ecs: &World, ctx: &mut BTerm) { Some(*ecs.fetch::()) ); ctx.add_sprite( - Rect::with_size(x * 16 + x_offset * 16, y * 16 + y_offset * 16, 16, 16), + Rect::with_size( + x * 16 + bounds.x_offset * 16, + y * 16 + bounds.y_offset * 16, + 16, + 16 + ), 0, tint, 0 // Ya @@ -88,8 +98,8 @@ pub fn render_camera(ecs: &World, ctx: &mut BTerm) { } } else if SHOW_BOUNDARIES { ctx.set( - x + x_offset, - y + y_offset, + x + bounds.x_offset, + y + bounds.y_offset, RGB::named(DARKSLATEGRAY), RGB::named(BLACK), to_cp437('#') @@ -117,9 +127,14 @@ pub fn render_camera(ecs: &World, ctx: &mut BTerm) { data.sort_by(|&a, &b| b.1.render_order.cmp(&a.1.render_order)); for (pos, render, ent, _hidden) in data.iter() { let idx = map.xy_idx(pos.x, pos.y); - let entity_offset_x = pos.x - min_x; - let entity_offset_y = pos.y - min_y; - if pos.x < max_x && pos.y < max_y && pos.x >= min_x && pos.y >= min_y { + let entity_offset_x = pos.x - bounds.min_x; + let entity_offset_y = pos.y - bounds.min_y; + if + pos.x < bounds.max_x && + pos.y < bounds.max_y && + pos.x >= bounds.min_x && + pos.y >= bounds.min_y + { let mut draw = false; let mut fg = render.fg; let bg = BLACK; @@ -152,8 +167,8 @@ pub fn render_camera(ecs: &World, ctx: &mut BTerm) { ctx.set_active_console(0); ctx.add_sprite( Rect::with_size( - entity_offset_x * 16 + x_offset * 16, - entity_offset_y * 16 + y_offset * 16, + entity_offset_x * 16 + bounds.x_offset * 16, + entity_offset_y * 16 + bounds.y_offset * 16, 16, 16 ), @@ -164,8 +179,8 @@ pub fn render_camera(ecs: &World, ctx: &mut BTerm) { ctx.set_active_console(ENTITY_LAYER); } else { ctx.set( - entity_offset_x + x_offset, - entity_offset_y + y_offset, + entity_offset_x + bounds.x_offset, + entity_offset_y + bounds.y_offset, fg, bg, render.glyph @@ -176,8 +191,8 @@ pub fn render_camera(ecs: &World, ctx: &mut BTerm) { ctx.set_active_console(HP_BAR_LAYER); crate::gui::draw_lerping_bar( ctx, - (entity_offset_x + x_offset) * 16 + 2, - (entity_offset_y + y_offset) * 16 - 1, + (entity_offset_x + bounds.x_offset) * 16 + 2, + (entity_offset_y + bounds.y_offset) * 16 - 1, 14, pool.hit_points.current, pool.hit_points.max, diff --git a/src/gui/farlook.rs b/src/gui/farlook.rs index 1e29daa..b346e0f 100644 --- a/src/gui/farlook.rs +++ b/src/gui/farlook.rs @@ -1,11 +1,4 @@ -use super::{ - State, - RunState, - tooltip::draw_tooltips, - camera::get_screen_bounds, - VIEWPORT_H, - VIEWPORT_W, -}; +use super::{ State, RunState, tooltip::draw_tooltips, camera::get_offset, VIEWPORT_H, VIEWPORT_W }; use bracket_lib::prelude::*; #[derive(PartialEq, Copy, Clone)] @@ -19,19 +12,19 @@ pub enum FarlookResult { pub fn show_farlook(gs: &mut State, ctx: &mut BTerm) -> FarlookResult { let runstate = gs.ecs.fetch::(); - let (_min_x, _max_x, _min_y, _max_y, x_offset, y_offset) = get_screen_bounds(&gs.ecs); + let offsets = get_offset(); ctx.print_color( - 1 + x_offset, - 1 + y_offset, + 1 + offsets.x, + 1 + offsets.y, RGB::named(WHITE), RGB::named(BLACK), "Look at what? [move keys][Esc.]" ); if let RunState::Farlook { x, y } = *runstate { - let x = x.clamp(x_offset, x_offset - 1 + VIEWPORT_W); - let y = y.clamp(y_offset, y_offset - 1 + VIEWPORT_H); + let x = x.clamp(offsets.x, offsets.x - 1 + VIEWPORT_W); + let y = y.clamp(offsets.y, offsets.y - 1 + VIEWPORT_H); ctx.set(x, y, RGB::named(WHITE), RGB::named(BLACK), to_cp437('X')); draw_tooltips(&gs.ecs, ctx, Some((x, y))); @@ -55,6 +48,6 @@ pub fn show_farlook(gs: &mut State, ctx: &mut BTerm) -> FarlookResult { } else { let ppos = gs.ecs.fetch::(); // TODO: PPOS + offsets (should get these from screen_bounds()) - return FarlookResult::NoResponse { x: ppos.x + x_offset, y: ppos.x + y_offset }; + return FarlookResult::NoResponse { x: ppos.x + offsets.x, y: ppos.x + offsets.y }; } } diff --git a/src/gui/identify_menu.rs b/src/gui/identify_menu.rs index af7f9d3..fde6ccd 100644 --- a/src/gui/identify_menu.rs +++ b/src/gui/identify_menu.rs @@ -122,12 +122,12 @@ pub fn identify(gs: &mut State, ctx: &mut BTerm) -> (ItemMenuResult, Option RunState ) -> RunState { - let (_, _, _, _, x_offset, y_offset) = camera::get_screen_bounds(ecs); + let offsets = camera::get_offset(); ctx.print_color( - 1 + x_offset, - 1 + y_offset, + 1 + offsets.x, + 1 + offsets.y, RGB::named(WHITE), RGB::named(BLACK), "In what direction? [0-9]/[YUHJKLBN]" @@ -1191,14 +1191,14 @@ pub fn ranged_target( range: i32, aoe: i32 ) -> (TargetResult, Option) { - let (min_x, max_x, min_y, max_y, x_offset, y_offset) = camera::get_screen_bounds(&gs.ecs); + let bounds = camera::get_screen_bounds(&gs.ecs); let player_entity = gs.ecs.fetch::(); let player_pos = gs.ecs.fetch::(); let viewsheds = gs.ecs.read_storage::(); ctx.print_color( - 1 + x_offset, - 1 + y_offset, + 1 + bounds.x_offset, + 1 + bounds.y_offset, RGB::named(WHITE), RGB::named(BLACK), "Targeting which tile? [mouse input]" @@ -1212,15 +1212,19 @@ pub fn ranged_target( for idx in visible.visible_tiles.iter() { let distance = DistanceAlg::Pythagoras.distance2d(*player_pos, *idx); if distance <= (range as f32) { - let screen_x = idx.x - min_x; - let screen_y = idx.y - min_y; + let screen_x = idx.x - bounds.min_x; + let screen_y = idx.y - bounds.min_y; if screen_x > 1 && - screen_x < max_x - min_x - 1 && + screen_x < bounds.max_x - bounds.min_x - 1 && screen_y > 1 && - screen_y < max_y - min_y - 1 + screen_y < bounds.max_y - bounds.min_y - 1 { - ctx.set_bg(screen_x + x_offset, screen_y + y_offset, TARGETING_VALID_COL); + ctx.set_bg( + screen_x + bounds.x_offset, + screen_y + bounds.y_offset, + TARGETING_VALID_COL + ); available_cells.push(idx); } } @@ -1231,13 +1235,13 @@ pub fn ranged_target( // Draw mouse cursor let mouse_pos = (x, y); - let (min_x, _max_x, min_y, _max_y, x_offset, y_offset) = camera::get_screen_bounds(&gs.ecs); - let x = x.clamp(x_offset, x_offset - 1 + VIEWPORT_W); - let y = y.clamp(y_offset, y_offset - 1 + VIEWPORT_H); + let bounds = camera::get_screen_bounds(&gs.ecs); + let x = x.clamp(bounds.x_offset, bounds.x_offset - 1 + VIEWPORT_W); + let y = y.clamp(bounds.y_offset, bounds.y_offset - 1 + VIEWPORT_H); let mut mouse_pos_adjusted = mouse_pos; - mouse_pos_adjusted.0 += min_x - x_offset; - mouse_pos_adjusted.1 += min_y - y_offset; + mouse_pos_adjusted.0 += bounds.min_x - bounds.x_offset; + mouse_pos_adjusted.1 += bounds.min_y - bounds.y_offset; let map = gs.ecs.fetch::(); let mut valid_target = false; for idx in available_cells.iter() { @@ -1257,8 +1261,8 @@ pub fn ranged_target( continue; } ctx.set( - point.x + x_offset - min_x, - point.y + y_offset - min_y, + point.x + bounds.x_offset - bounds.min_x, + point.y + bounds.y_offset - bounds.min_y, RGB::named(TARGETING_LINE_COL), RGB::named(TARGETING_VALID_COL), to_cp437('~') @@ -1285,7 +1289,11 @@ pub fn ranged_target( let col2 = BLACK; ((col1.0 + col2.0) / 2, (col1.1 + col2.1) / 2, (col1.2 + col2.2) / 2) }; - ctx.set_bg(tile.x - min_x + x_offset, tile.y - min_y + y_offset, bg); + ctx.set_bg( + tile.x - bounds.min_x + bounds.x_offset, + tile.y - bounds.min_y + bounds.y_offset, + bg + ); } } diff --git a/src/gui/remove_curse_menu.rs b/src/gui/remove_curse_menu.rs index 73003ca..90bf47a 100644 --- a/src/gui/remove_curse_menu.rs +++ b/src/gui/remove_curse_menu.rs @@ -117,12 +117,12 @@ pub fn remove_curse(gs: &mut State, ctx: &mut BTerm) -> (ItemMenuResult, Option< } // Get display args let width = get_max_inventory_width(&player_inventory); - let (_, _, _, _, x_offset, y_offset) = crate::camera::get_screen_bounds(&gs.ecs); - let (x, y) = (x_offset + 1, y_offset + 3); + let offsets = crate::camera::get_offset(); + let (x, y) = (offsets.x + 1, offsets.y + 3); // Draw menu ctx.print_color( - 1 + x_offset, - 1 + y_offset, + 1 + offsets.x, + 1 + offsets.y, RGB::named(WHITE), RGB::named(BLACK), "Decurse which item? [aA-zZ][Esc.]" diff --git a/src/gui/tooltip.rs b/src/gui/tooltip.rs index f05d790..5d69795 100644 --- a/src/gui/tooltip.rs +++ b/src/gui/tooltip.rs @@ -64,7 +64,7 @@ impl Tooltip { #[rustfmt::skip] pub fn draw_tooltips(ecs: &World, ctx: &mut BTerm, xy: Option<(i32, i32)>) { - let (min_x, _max_x, min_y, _max_y, x_offset, y_offset) = get_screen_bounds(ecs); + let bounds = get_screen_bounds(ecs); let map = ecs.fetch::(); let names = ecs.read_storage::(); let positions = ecs.read_storage::(); @@ -77,8 +77,8 @@ pub fn draw_tooltips(ecs: &World, ctx: &mut BTerm, xy: Option<(i32, i32)>) { let mouse_pos = if xy.is_none() { ctx.mouse_pos() } else { xy.unwrap() }; let mut mouse_pos_adjusted = mouse_pos; - mouse_pos_adjusted.0 += min_x - x_offset; - mouse_pos_adjusted.1 += min_y - y_offset; + mouse_pos_adjusted.0 += bounds.min_x - bounds.x_offset; + mouse_pos_adjusted.1 += bounds.min_y - bounds.y_offset; if mouse_pos_adjusted.0 >= map.width || mouse_pos_adjusted.1 >= map.height || mouse_pos_adjusted.1 < 0 // Might need to be 1, and -1 from map height/width. diff --git a/src/main.rs b/src/main.rs index 134b918..821e281 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,9 +7,9 @@ use specs::saveload::{ SimpleMarker, SimpleMarkerAllocator }; use bracket_lib::prelude::*; use std::collections::HashMap; -const TILESIZE: u32 = 16; -const DISPLAYWIDTH: u32 = 100 * TILESIZE; -const DISPLAYHEIGHT: u32 = 56 * TILESIZE; +const TILESIZE: f32 = 16.0; +const DISPLAYWIDTH: u32 = 100 * (TILESIZE as u32); +const DISPLAYHEIGHT: u32 = 56 * (TILESIZE as u32); #[notan_main] fn main() -> Result<(), String> { @@ -155,8 +155,11 @@ enum DrawType { VisibleAndRemember, Telepathy, } + +#[derive(PartialEq, Eq, Hash)] struct DrawKey { - idx: usize, + x: i32, + y: i32, render_order: i32, } struct DrawInfo { @@ -165,9 +168,10 @@ struct DrawInfo { } fn draw_camera(ecs: &World, draw: &mut Draw, atlas: &HashMap) { let map = ecs.fetch::(); - let bounds = crate::camera::get_screen_bounds(ecs); - render_map_in_view(&*map, ecs, draw, bounds); + + render_map_in_view(&*map, ecs, draw, atlas); { + let bounds = crate::camera::get_screen_bounds(ecs); let positions = ecs.read_storage::(); let renderables = ecs.read_storage::(); let hidden = ecs.read_storage::(); @@ -180,8 +184,8 @@ fn draw_camera(ecs: &World, draw: &mut Draw, atlas: &HashMap) { let mut to_draw: HashMap = HashMap::new(); for (pos, render, e, _h) in data.iter() { let idx = map.xy_idx(pos.x, pos.y); - let entity_offset_x = pos.x - bounds.x_offset; - let entity_offset_y = pos.y - bounds.y_offset; + let offset_x = pos.x - bounds.min_x + bounds.x_offset; + let offset_y = pos.y - bounds.min_y + bounds.y_offset; if crate::camera::in_bounds( pos.x, @@ -211,6 +215,8 @@ fn draw_camera(ecs: &World, draw: &mut Draw, atlas: &HashMap) { // draw these, but it uses a unique enum variant so // it can be treated differently if needed in future. DrawType::Telepathy + } else { + DrawType::None } } else { // If we don't see it, and we don't sense it with @@ -219,16 +225,17 @@ fn draw_camera(ecs: &World, draw: &mut Draw, atlas: &HashMap) { }; match draw_type { DrawType::None => {} - _ => + _ => { to_draw.insert( - DrawKey { idx, render_order: render.render_order }, - DrawInfo { e, draw_type } - ), + DrawKey { x: offset_x, y: offset_y, render_order: render.render_order }, + DrawInfo { e: *e, draw_type } + ); + } } } } let mut entries: Vec<(&DrawKey, &DrawInfo)> = to_draw.iter().collect(); - entries.sort_by_key(|&(k, _v)| *k.render_order); + entries.sort_by_key(|&(k, _v)| k.render_order); for entry in entries.iter() { match entry.1.draw_type { DrawType::Visible | DrawType::Telepathy => { @@ -237,10 +244,17 @@ fn draw_camera(ecs: &World, draw: &mut Draw, atlas: &HashMap) { // Draw health bar } } + draw.image(atlas.get("ui_heart_full").unwrap()).position( + (entry.0.x as f32) * TILESIZE, + (entry.0.y as f32) * TILESIZE + ); // Draw entity } DrawType::VisibleAndRemember => { - // Draw it, and remember it + draw.image(atlas.get("ui_crystal_full").unwrap()).position( + (entry.0.x as f32) * TILESIZE, + (entry.0.y as f32) * TILESIZE + ); } _ => {} } @@ -248,8 +262,8 @@ fn draw_camera(ecs: &World, draw: &mut Draw, atlas: &HashMap) { } } -use crate::camera::ScreenBounds; -fn render_map_in_view(map: &Map, ecs: &World, draw: &mut Draw, bounds: ScreenBounds) { +fn render_map_in_view(map: &Map, ecs: &World, draw: &mut Draw, atlas: &HashMap) { + let bounds = crate::camera::get_screen_bounds(ecs); for tile_y in bounds.min_y..bounds.max_y { for tile_x in bounds.min_x..bounds.max_x { if crate::camera::in_bounds(tile_x, tile_y, 0, 0, map.width, map.height) { @@ -286,8 +300,7 @@ fn render_map_in_view(map: &Map, ecs: &World, draw: &mut Draw, bounds: ScreenBou fn draw(app: &mut App, gfx: &mut Graphics, gs: &mut State) { let mut draw = gfx.create_draw(); draw.clear(Color::BLACK); - - match gs.ecs.fetch::() { + match *gs.ecs.fetch::() { | RunState::MainMenu { .. } | RunState::CharacterCreation { .. } | RunState::PreRun { .. } => {} @@ -299,7 +312,7 @@ fn draw(app: &mut App, gfx: &mut Graphics, gs: &mut State) { let map = gs.ecs.fetch::(); let ppos = gs.ecs.fetch::(); let offsets = crate::camera::get_offset(); - let px = idx_to_px(map.xy_idx(ppos.x + offsets.0, ppos.y + offsets.1), &map); + let px = idx_to_px(map.xy_idx(ppos.x + offsets.x, ppos.y + offsets.y), &map); draw.image(gs.atlas.get("ui_heart_full").unwrap()).position(px.0, px.1); // Render batch gfx.render(&draw); diff --git a/src/player.rs b/src/player.rs index 306ec64..bac7a99 100644 --- a/src/player.rs +++ b/src/player.rs @@ -749,9 +749,12 @@ pub fn player_input(gs: &mut State, ctx: &mut App, on_overmap: bool) -> RunState return RunState::SaveGame; } KeyCode::X => { - let (min_x, _max_x, min_y, _max_y, x_offset, y_offset) = get_screen_bounds(&gs.ecs); + let bounds = get_screen_bounds(&gs.ecs); let ppos = gs.ecs.fetch::(); - let (x, y) = (ppos.x + x_offset - min_x, ppos.y + y_offset - min_y); + let (x, y) = ( + ppos.x + bounds.x_offset - bounds.min_x, + ppos.y + bounds.y_offset - bounds.min_y, + ); return RunState::Farlook { x, y }; } _ => {} diff --git a/src/states/state.rs b/src/states/state.rs index 5c99206..9185e0d 100644 --- a/src/states/state.rs +++ b/src/states/state.rs @@ -446,21 +446,20 @@ impl State { if let Some(ranged_item) = ranged_item { let is_aoe = self.ecs.read_storage::(); let aoe_item = is_aoe.get(item_entity); - let (min_x, _max_x, min_y, _max_y, x_offset, y_offset) = - camera::get_screen_bounds(&self.ecs); + let bounds = camera::get_screen_bounds(&self.ecs); let ppos = self.ecs.fetch::(); if let Some(aoe_item) = aoe_item { new_runstate = RunState::ShowTargeting { - x: ppos.x + x_offset - min_x, - y: ppos.y + y_offset - min_y, + x: ppos.x + bounds.x_offset - bounds.min_x, + y: ppos.y + bounds.y_offset - bounds.min_y, range: ranged_item.range, item: item_entity, aoe: aoe_item.radius, }; } else { new_runstate = RunState::ShowTargeting { - x: ppos.x + x_offset - min_x, - y: ppos.y + y_offset - min_y, + x: ppos.x + bounds.x_offset - bounds.min_x, + y: ppos.y + bounds.y_offset - bounds.min_y, range: ranged_item.range, item: item_entity, aoe: 0,