map memory
This commit is contained in:
parent
054468bbae
commit
cfbe4098b7
3 changed files with 86 additions and 60 deletions
92
src/main.rs
92
src/main.rs
|
|
@ -154,7 +154,6 @@ const SHOW_BOUNDARIES: bool = false; // Config setting
|
|||
enum DrawType {
|
||||
None,
|
||||
Visible,
|
||||
VisibleAndRemember,
|
||||
Telepathy,
|
||||
}
|
||||
|
||||
|
|
@ -170,12 +169,12 @@ struct DrawInfo {
|
|||
}
|
||||
|
||||
fn draw_camera(
|
||||
map: &Map,
|
||||
ecs: &World,
|
||||
draw: &mut Draw,
|
||||
atlas: &HashMap<String, Texture>,
|
||||
font: ¬an::draw::Font
|
||||
) {
|
||||
let map = ecs.fetch::<Map>();
|
||||
render_map_in_view(&*map, ecs, draw, atlas, false);
|
||||
{
|
||||
let bounds = crate::camera::get_screen_bounds(ecs, false);
|
||||
|
|
@ -204,17 +203,8 @@ fn draw_camera(
|
|||
)
|
||||
{
|
||||
let draw_type = if map.visible_tiles[idx] {
|
||||
let is_prop = props.get(*e);
|
||||
let is_item = items.get(*e);
|
||||
if is_prop.is_some() || is_item.is_some() {
|
||||
// If it's a static entity, we want to draw it, and
|
||||
// also save it's location so that we remember where
|
||||
// it was last seen after it leaves vision.
|
||||
DrawType::VisibleAndRemember
|
||||
} else {
|
||||
// If it's anything else, just draw it.
|
||||
DrawType::Visible
|
||||
}
|
||||
} else if map.telepath_tiles[idx] {
|
||||
let has_mind = minds.get(*e);
|
||||
if has_mind.is_some() {
|
||||
|
|
@ -317,50 +307,6 @@ fn draw_camera(
|
|||
.v_align_middle();
|
||||
}
|
||||
}
|
||||
DrawType::VisibleAndRemember => {
|
||||
// TODO: PUT THIS INTO A FUNCTION!
|
||||
let renderable = renderables.get(entry.1.e).unwrap();
|
||||
if let Some(spriteinfo) = &renderable.sprite {
|
||||
let id = if let Some(sprite) = atlas.get(&spriteinfo.id) {
|
||||
sprite
|
||||
} else {
|
||||
panic!("No entity sprite found for ID: {}", spriteinfo.id);
|
||||
};
|
||||
draw.image(id)
|
||||
.position(
|
||||
((entry.0.x as f32) + spriteinfo.offset.0) * TILESIZE,
|
||||
((entry.0.y as f32) + spriteinfo.offset.1) * TILESIZE
|
||||
)
|
||||
.color(
|
||||
if spriteinfo.recolour {
|
||||
Color::from_rgb(
|
||||
renderable.fg.r,
|
||||
renderable.fg.g,
|
||||
renderable.fg.b
|
||||
)
|
||||
} else {
|
||||
Color::WHITE
|
||||
}
|
||||
);
|
||||
} else {
|
||||
// Fallback to drawing text.
|
||||
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)
|
||||
.h_align_center()
|
||||
.v_align_middle();
|
||||
}
|
||||
// TODO: Update map memory.
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
|
@ -408,6 +354,34 @@ fn render_map_in_view(
|
|||
)
|
||||
.color(tint);
|
||||
}
|
||||
if !map.visible_tiles[idx] {
|
||||
// Recall map memory. TODO: Improve this? Optimize? Do we need to remember more fields?
|
||||
if let Some(memories) = map.memory.get(&idx) {
|
||||
let mut sorted: Vec<_> = memories.iter().collect();
|
||||
sorted.sort_by(|a, b| a.render_order.cmp(&b.render_order));
|
||||
for memory in sorted.iter() {
|
||||
let sprite = if let Some(sprite) = atlas.get(&memory.sprite) {
|
||||
sprite
|
||||
} else {
|
||||
panic!("No sprite found for ID: {}", memory.sprite);
|
||||
};
|
||||
draw.image(sprite)
|
||||
.position(
|
||||
(((x + bounds.x_offset) as f32) + memory.offset.0) *
|
||||
TILESIZE,
|
||||
(((y + bounds.y_offset) as f32) + memory.offset.1) *
|
||||
TILESIZE
|
||||
)
|
||||
.color(
|
||||
if memory.recolour {
|
||||
Color::from_rgb(memory.fg.r, memory.fg.g, memory.fg.b)
|
||||
} else {
|
||||
Color::from_rgb(0.75, 0.75, 0.75)
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if SHOW_BOUNDARIES {
|
||||
// TODO: Draw boundaries
|
||||
|
|
@ -524,7 +498,8 @@ 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>() {
|
||||
let runstate = *gs.ecs.fetch::<RunState>();
|
||||
match runstate {
|
||||
| RunState::MainMenu { .. }
|
||||
| RunState::CharacterCreation { .. }
|
||||
| RunState::PreRun { .. } => {}
|
||||
|
|
@ -541,13 +516,14 @@ fn draw(_app: &mut App, gfx: &mut Graphics, gs: &mut State) {
|
|||
}
|
||||
}
|
||||
_ => {
|
||||
let map = gs.ecs.fetch::<Map>();
|
||||
draw_bg(&gs.ecs, &mut draw, &gs.atlas);
|
||||
draw_camera(&gs.ecs, &mut draw, &gs.atlas, &gs.font);
|
||||
draw_camera(&*map, &gs.ecs, &mut draw, &gs.atlas, &gs.font);
|
||||
gui::draw_ui2(&gs.ecs, &mut draw, &gs.atlas, &gs.font);
|
||||
log = true;
|
||||
}
|
||||
}
|
||||
match *gs.ecs.fetch::<RunState>() {
|
||||
match runstate {
|
||||
RunState::Farlook { x, y } => {
|
||||
gui::draw_farlook(x, y, &mut draw, &gs.atlas);
|
||||
//draw_tooltips(&gs.ecs, ctx, Some((x, y))); TODO: Put this in draw loop
|
||||
|
|
|
|||
|
|
@ -26,6 +26,15 @@ use super::consts::visuals::{
|
|||
// i.e. on a map size of 40*40, only entities to the left of the player are rendered.
|
||||
// on a map size of 42*42, the player can see entities up to 2 tiles to their right.
|
||||
|
||||
#[derive(Clone, Serialize, Deserialize)]
|
||||
pub struct MapMemory {
|
||||
pub sprite: String,
|
||||
pub fg: RGB,
|
||||
pub recolour: bool,
|
||||
pub offset: (f32, f32),
|
||||
pub render_order: i32,
|
||||
}
|
||||
|
||||
#[derive(Default, Serialize, Deserialize, Clone)]
|
||||
pub struct Map {
|
||||
pub overmap: bool,
|
||||
|
|
@ -33,6 +42,7 @@ pub struct Map {
|
|||
pub width: i32,
|
||||
pub height: i32,
|
||||
pub revealed_tiles: Vec<bool>,
|
||||
pub memory: HashMap<usize, Vec<MapMemory>>,
|
||||
pub visible_tiles: Vec<bool>,
|
||||
pub lit_tiles: Vec<bool>,
|
||||
pub telepath_tiles: Vec<bool>,
|
||||
|
|
@ -71,6 +81,7 @@ impl Map {
|
|||
width: width,
|
||||
height: height,
|
||||
revealed_tiles: vec![false; map_tile_count],
|
||||
memory: HashMap::new(),
|
||||
visible_tiles: vec![false; map_tile_count],
|
||||
lit_tiles: vec![true; map_tile_count], // NYI: Light sources. Once those exist, we can set this to false.
|
||||
telepath_tiles: vec![false; map_tile_count],
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@ use super::{
|
|||
Telepath,
|
||||
Viewshed,
|
||||
Renderable,
|
||||
Prop,
|
||||
Item,
|
||||
gui::renderable_colour,
|
||||
tile_blocks_telepathy,
|
||||
};
|
||||
|
|
@ -35,6 +37,8 @@ impl<'a> System<'a> for VisibilitySystem {
|
|||
ReadStorage<'a, Blind>,
|
||||
ReadStorage<'a, BlocksVisibility>,
|
||||
ReadStorage<'a, Renderable>,
|
||||
ReadStorage<'a, Prop>,
|
||||
ReadStorage<'a, Item>,
|
||||
);
|
||||
|
||||
fn run(&mut self, data: Self::SystemData) {
|
||||
|
|
@ -51,6 +55,8 @@ impl<'a> System<'a> for VisibilitySystem {
|
|||
blind_entities,
|
||||
blocks_visibility,
|
||||
renderables,
|
||||
prop,
|
||||
item,
|
||||
) = data;
|
||||
|
||||
map.view_blocked.clear();
|
||||
|
|
@ -59,6 +65,7 @@ impl<'a> System<'a> for VisibilitySystem {
|
|||
map.view_blocked.insert(idx);
|
||||
}
|
||||
|
||||
let mut player_was_dirty = false;
|
||||
for (ent, viewshed, pos) in (&entities, &mut viewshed, &pos).join() {
|
||||
if viewshed.dirty {
|
||||
viewshed.dirty = false;
|
||||
|
|
@ -81,6 +88,7 @@ impl<'a> System<'a> for VisibilitySystem {
|
|||
// If this is the player, reveal what they can see
|
||||
let _p: Option<&Player> = player.get(ent);
|
||||
if let Some(_p) = _p {
|
||||
player_was_dirty = true;
|
||||
for t in map.visible_tiles.iter_mut() {
|
||||
*t = false;
|
||||
}
|
||||
|
|
@ -139,6 +147,37 @@ impl<'a> System<'a> for VisibilitySystem {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if player_was_dirty {
|
||||
// Refresh the memory of our visible tiles, by removing whatever
|
||||
// was stored for every index we can currently see, and placing
|
||||
// back in updated data.
|
||||
let mut to_remove: Vec<usize> = Vec::new();
|
||||
for (i, &t) in map.visible_tiles.iter().enumerate() {
|
||||
if t {
|
||||
to_remove.push(i);
|
||||
}
|
||||
}
|
||||
for idx in to_remove.iter() {
|
||||
map.memory.remove(idx);
|
||||
}
|
||||
for (e, r, p, _h) in (&entities, &renderables, &pos, !&hidden).join() {
|
||||
if prop.get(e).is_some() || item.get(e).is_some() {
|
||||
let idx = map.xy_idx(p.x, p.y);
|
||||
if map.visible_tiles[idx] {
|
||||
if let Some(spriteinfo) = &r.sprite {
|
||||
map.memory.entry(idx).or_insert(Vec::new()).push(crate::MapMemory {
|
||||
sprite: spriteinfo.id.clone(),
|
||||
fg: r.fg,
|
||||
recolour: spriteinfo.recolour,
|
||||
offset: spriteinfo.offset,
|
||||
render_order: r.render_order,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue