optional darken by distance and viewshed multiplier

This commit is contained in:
Llywelwyn 2023-08-23 00:00:44 +01:00
parent f8c74ea6f9
commit 2c7671b348
7 changed files with 40 additions and 16 deletions

View file

@ -33,7 +33,8 @@ pub fn render_camera(ecs: &World, ctx: &mut Rltk) {
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] {
let (glyph, fg, bg) = crate::map::themes::get_tile_renderables_for_id(idx, &*map);
let (glyph, fg, bg) =
crate::map::themes::get_tile_renderables_for_id(idx, &*map, Some(*ecs.fetch::<Point>()));
ctx.set(x + x_offset, y + y_offset, fg, bg, glyph);
}
} else if SHOW_BOUNDARIES {
@ -63,18 +64,15 @@ pub fn render_camera(ecs: &World, ctx: &mut Rltk) {
if pos.x < max_x && pos.y < max_y && pos.x >= min_x && pos.y >= min_y {
let mut draw = false;
let mut fg = render.fg;
let mut bg = if render.bg == (RGB { r: 0.0, g: 0.0, b: 0.0 }) {
crate::map::themes::get_tile_renderables_for_id(idx, &*map).2
} else {
render.bg
};
let mut bg = crate::map::themes::get_tile_renderables_for_id(idx, &*map, Some(*ecs.fetch::<Point>())).2;
// Draw entities on visible tiles
if map.visible_tiles[idx] {
draw = true;
} else {
fg = fg.mul(0.75);
fg = fg.mul(crate::map::NON_VISIBLE_MULTIPLIER);
// We don't darken BG, because get_tile_renderables_for_id handles this.
}
// Draw entities with minds within telepath range
if !draw {
if map.telepath_tiles[idx] {
@ -124,7 +122,7 @@ pub fn render_debug_map(map: &Map, ctx: &mut Rltk) {
if tx >= 0 && tx < map_width && ty >= 0 && ty < map_height {
let idx = map.xy_idx(tx, ty);
if map.revealed_tiles[idx] {
let (glyph, fg, bg) = crate::map::themes::get_tile_renderables_for_id(idx, &*map);
let (glyph, fg, bg) = crate::map::themes::get_tile_renderables_for_id(idx, &*map, None);
ctx.set(x, y, fg, bg, glyph);
}
} else if SHOW_BOUNDARIES {

View file

@ -4,7 +4,6 @@ use super::{
};
use crate::{
gamelog, Beatitude, Entity, Equipped, InBackpack, Item, MasterDungeonMap, Name, ObfuscatedName, Renderable, State,
BUC,
};
use rltk::prelude::*;
use specs::prelude::*;

View file

@ -1,4 +1,8 @@
pub const NON_VISIBLE_MULTIPLIER: f32 = 0.7;
pub const NON_VISIBLE_MULTIPLIER: f32 = 0.3;
pub const MAX_DARKENING: f32 = 0.3;
pub const START_DARKEN_AT_N_TILES: f32 = 9.0;
pub const MAX_DARKEN_AT_N_TILES: f32 = 12.0;
pub const BLOODSTAIN_COLOUR: (u8, u8, u8) = (153, 0, 0);
// DEFAULT THEME
@ -14,7 +18,7 @@ pub const GRAVEL_COLOUR: (u8, u8, u8) = (26, 26, 53);
pub const ROAD_COLOUR: (u8, u8, u8) = (8, 38, 40);
pub const GRASS_COLOUR: (u8, u8, u8) = (9, 65, 6);
pub const FOLIAGE_COLOUR: (u8, u8, u8) = (5, 60, 5);
pub const HEAVY_FOLIAGE_COLOUR: (u8, u8, u8) = (5, 55, 5);
pub const HEAVY_FOLIAGE_COLOUR: (u8, u8, u8) = (5, 60, 5);
pub const SAND_COLOUR: (u8, u8, u8) = (70, 70, 21);
pub const SHALLOW_WATER_COLOUR: (u8, u8, u8) = (24, 47, 99);
pub const DEEP_WATER_COLOUR: (u8, u8, u8) = (18, 33, 63);

View file

@ -10,6 +10,7 @@ pub use interval_spawning_system::try_spawn_interval;
pub mod dungeon;
pub use dungeon::{level_transition, MasterDungeonMap};
pub mod themes;
pub use colours::NON_VISIBLE_MULTIPLIER;
// FIXME: If the map size gets too small, entities stop being rendered starting from the right.
// i.e. on a map size of 40*40, only entities to the left of the player are rendered.

View file

@ -1,8 +1,10 @@
use super::{colours::*, glyphs::*, Map, TileType};
use rltk::RGB;
use super::{colours::*, glyphs::*, Map, Point, TileType};
use rltk::prelude::*;
use std::ops::{Add, Mul};
pub fn get_tile_renderables_for_id(idx: usize, map: &Map) -> (rltk::FontCharType, RGB, RGB) {
const DARKEN_TILES_BY_DISTANCE: bool = true;
pub fn get_tile_renderables_for_id(idx: usize, map: &Map, other_pos: Option<Point>) -> (rltk::FontCharType, RGB, RGB) {
let (glyph, mut fg, mut bg) = match map.id {
2 => get_forest_theme_renderables(idx, map),
_ => get_default_theme_renderables(idx, map),
@ -19,6 +21,11 @@ pub fn get_tile_renderables_for_id(idx: usize, map: &Map) -> (rltk::FontCharType
(fg, bg) = apply_colour_offset(fg, bg, map, idx);
bg = apply_bloodstain_if_necessary(bg, map, idx);
(fg, bg) = darken_if_not_visible(fg, bg, map, idx);
if other_pos.is_some() && DARKEN_TILES_BY_DISTANCE {
let distance =
darken_by_distance(Point::new(idx as i32 % map.width, idx as i32 / map.width), other_pos.unwrap());
(fg, bg) = (fg.mul(distance), bg.mul(distance));
}
return (glyph, fg, bg);
}
@ -241,3 +248,11 @@ pub fn multiply_by_float(rgb: rltk::RGB, offsets: (f32, f32, f32)) -> RGB {
return rltk::RGB::from_f32(r, g, b);
}
fn darken_by_distance(pos: Point, other_pos: Point) -> f32 {
let distance = DistanceAlg::Pythagoras.distance2d(pos, other_pos) as f32; // Get distance in tiles.
let interp_factor = (distance - START_DARKEN_AT_N_TILES)
/ (MAX_DARKEN_AT_N_TILES * crate::spawner::VIEWSHED_MOD - START_DARKEN_AT_N_TILES);
let interp_factor = interp_factor.max(0.0).min(1.0); // Clamp [0-1]
return 1.0 - interp_factor * (1.0 - MAX_DARKENING);
}

View file

@ -3,6 +3,7 @@ use crate::components::*;
use crate::gamesystem::*;
use crate::gui::Ancestry;
use crate::random_table::RandomTable;
use crate::spawner;
use crate::LOG_SPAWNING;
use regex::Regex;
use rltk::prelude::*;
@ -380,7 +381,11 @@ pub fn spawn_named_mob(
eb = ecs.create_entity().marked::<SimpleMarker<SerializeMe>>();
eb = spawn_position(pos, eb, key, raws);
eb = eb.with(Name { name: mob_template.name.clone(), plural: mob_template.name.clone() });
eb = eb.with(Viewshed { visible_tiles: Vec::new(), range: mob_template.vision_range, dirty: true });
eb = eb.with(Viewshed {
visible_tiles: Vec::new(),
range: (mob_template.vision_range as f32 * spawner::VIEWSHED_MOD) as i32,
dirty: true,
});
if let Some(telepath) = &mob_template.telepathy_range {
eb = eb.with(Telepath { telepath_tiles: Vec::new(), range: *telepath, dirty: true });
}

View file

@ -9,6 +9,8 @@ use specs::prelude::*;
use specs::saveload::{MarkedBuilder, SimpleMarker};
use std::collections::HashMap;
pub const VIEWSHED_MOD: f32 = 1.25;
/// Spawns the player and returns his/her entity object.
pub fn player(ecs: &mut World, player_x: i32, player_y: i32) -> Entity {
let mut skills = Skills { skills: HashMap::new() };
@ -30,7 +32,7 @@ pub fn player(ecs: &mut World, player_x: i32, player_y: i32) -> Entity {
.with(Player {})
.with(Mind {})
.with(Faction { name: "player".to_string() })
.with(Viewshed { visible_tiles: Vec::new(), range: 12, dirty: true })
.with(Viewshed { visible_tiles: Vec::new(), range: (12 as f32 * VIEWSHED_MOD) as i32, dirty: true })
.with(Name { name: "you".to_string(), plural: "you".to_string() })
.with(HungerClock { state: HungerState::Satiated, duration: 1200 })
.with(Attributes {