From a54e604681229370de9cfa68cc9ec1563a53e93d Mon Sep 17 00:00:00 2001 From: Llywelwyn Date: Wed, 26 Jul 2023 02:30:25 +0100 Subject: [PATCH] town tweaks, themes --- src/camera.rs | 257 +-------------------------------------- src/map/mod.rs | 1 + src/map/themes.rs | 248 +++++++++++++++++++++++++++++++++++++ src/map/tiletype.rs | 4 + src/map_builders/town.rs | 13 +- 5 files changed, 268 insertions(+), 255 deletions(-) create mode 100644 src/map/themes.rs diff --git a/src/camera.rs b/src/camera.rs index 2ff126e..3325965 100644 --- a/src/camera.rs +++ b/src/camera.rs @@ -1,7 +1,6 @@ -use super::{Door, Hidden, Map, Mind, Position, Renderable, TileType}; +use super::{Door, Hidden, Map, Mind, Position, Renderable}; use rltk::{Point, Rltk, RGB}; use specs::prelude::*; -use std::ops::{Add, Mul}; const SHOW_BOUNDARIES: bool = false; @@ -37,7 +36,7 @@ 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) = get_tile_glyph(idx, &*map); + let (glyph, fg, bg) = crate::map::themes::get_tile_glyph(idx, &*map); ctx.set(x, y, fg, bg, glyph); } } else if SHOW_BOUNDARIES { @@ -66,14 +65,9 @@ pub fn render_camera(ecs: &World, ctx: &mut Rltk) { let entity_offset_y = pos.y - min_y; if entity_offset_x > 0 && entity_offset_x < map_width && entity_offset_y > 0 && entity_offset_y < map_height { - let offsets = map.colour_offset[idx]; let mut draw = false; - let mut fg = render.fg; - let mut bg = offset(render.bg, offsets); - // Get bloodstain colours - if map.bloodstains.contains(&idx) { - bg = bg.add(RGB::from_f32(0.6, 0., 0.)); - } + let fg = render.fg; + let (_glyph, _fg, bg) = crate::map::themes::get_tile_glyph(idx, &*map); // Draw entities on visible tiles if map.visible_tiles[idx] { draw = true; @@ -89,10 +83,6 @@ pub fn render_camera(ecs: &World, ctx: &mut Rltk) { let is_door = doors.get(*ent); if let Some(_) = is_door { if map.revealed_tiles[idx] { - if !map.visible_tiles[idx] { - fg = fg.mul(0.6); - bg = bg.mul(0.6); - } draw = true; } } @@ -104,243 +94,6 @@ pub fn render_camera(ecs: &World, ctx: &mut Rltk) { } } -fn offset(rgb: rltk::RGB, offsets: (f32, f32, f32)) -> RGB { - let r = rgb.r * offsets.0; - let g = rgb.g * offsets.1; - let b = rgb.b * offsets.2; - - return rltk::RGB::from_f32(r, g, b); -} - -fn get_tile_glyph(idx: usize, map: &Map) -> (rltk::FontCharType, RGB, RGB) { - let offsets = map.colour_offset[idx]; - let glyph: rltk::FontCharType; - let mut fg: RGB = RGB::new(); - let mut bg: RGB; - - let default_bg: RGB = RGB::from_u8(26, 45, 45); - - match map.tiles[idx] { - TileType::Floor => { - glyph = rltk::to_cp437('.'); - fg = RGB::from_f32(0.1, 0.8, 0.5); - bg = default_bg; - } - TileType::WoodFloor => { - glyph = rltk::to_cp437('.'); - bg = RGB::from_u8(47, 36, 28); - } - TileType::Fence => { - glyph = rltk::to_cp437('='); - fg = RGB::from_u8(66, 32, 6); - bg = RGB::from_u8(44, 34, 26); - } - TileType::Wall => { - let x = idx as i32 % map.width; - let y = idx as i32 / map.width; - glyph = wall_glyph(&*map, x, y); - fg = RGB::from_f32(0.6, 0.5, 0.25); - bg = default_bg; - } - TileType::DownStair => { - glyph = rltk::to_cp437('>'); - fg = RGB::from_f32(0., 1., 1.); - bg = default_bg; - } - TileType::Bridge => { - glyph = rltk::to_cp437('.'); - fg = default_bg; - bg = default_bg; - } - TileType::Gravel => { - glyph = rltk::to_cp437(';'); - bg = RGB::from_u8(26, 26, 36); - } - TileType::Road => { - glyph = rltk::to_cp437('~'); - //fg = RGB::from_u8(112, 105, 94); - bg = default_bg; - } - TileType::Grass => { - glyph = rltk::to_cp437('"'); - bg = RGB::from_u8(26, 45, 26); - } - TileType::Sand => { - glyph = rltk::to_cp437('.'); - bg = RGB::from_u8(54, 54, 28); - } - TileType::ShallowWater => { - glyph = rltk::to_cp437('~'); - bg = RGB::from_u8(34, 42, 62); - } - TileType::DeepWater => { - glyph = rltk::to_cp437('~'); - bg = RGB::from_u8(24, 30, 42); - } - } - if map.bloodstains.contains(&idx) { - bg = bg.add(RGB::from_f32(0.6, 0., 0.)); - } - - // If the foreground hasn't been changed, just add - // the bg to it. Otherwise, leave it as is. - if fg == RGB::new() { - fg = fg.add(bg).add(map.additional_fg_offset); - } - - fg = offset(fg, offsets); - bg = offset(bg, offsets); - - if !map.visible_tiles[idx] { - fg = fg.mul(0.75); - bg = bg.mul(0.75); - } - - return (glyph, fg, bg); -} - -fn is_revealed_and_wall(map: &Map, x: i32, y: i32) -> bool { - let idx = map.xy_idx(x, y); - map.tiles[idx] == TileType::Wall && map.revealed_tiles[idx] -} - -fn wall_glyph(map: &Map, x: i32, y: i32) -> rltk::FontCharType { - if x < 1 || x > map.width - 2 || y < 1 || y > map.height - 2 as i32 { - return 35; - } - let mut mask: u8 = 0; - let diagonals_matter: Vec = vec![7, 11, 13, 14, 15]; - - if is_revealed_and_wall(map, x, y - 1) { - // N - mask += 1; - } - if is_revealed_and_wall(map, x, y + 1) { - // S - mask += 2; - } - if is_revealed_and_wall(map, x - 1, y) { - // W - mask += 4; - } - if is_revealed_and_wall(map, x + 1, y) { - // E - mask += 8; - } - - if diagonals_matter.contains(&mask) { - if is_revealed_and_wall(map, x + 1, y - 1) { - // Top right - mask += 16; - } - if is_revealed_and_wall(map, x - 1, y - 1) { - // Top left - mask += 32; - } - if is_revealed_and_wall(map, x + 1, y + 1) { - // Bottom right - mask += 64; - } - if is_revealed_and_wall(map, x - 1, y + 1) { - // Bottom left - mask += 128; - } - } - - match mask { - 0 => 254, // ■ (254) square pillar; but maybe ○ (9) looks better - 1 => 186, // Wall only to the north - 2 => 186, // Wall only to the south - 3 => 186, // Wall to the north and south - 4 => 205, // Wall only to the west - 5 => 188, // Wall to the north and west - 6 => 187, // Wall to the south and west - 7 => 185, // Wall to the north, south and west - 8 => 205, // Wall only to the east - 9 => 200, // Wall to the north and east - 10 => 201, // Wall to the south and east - 11 => 204, // Wall to the north, south and east - 12 => 205, // Wall to the east and west - 13 => 202, // Wall to the east, west, and north - 14 => 203, // Wall to the east, west, and south - 15 => 206, // ╬ Wall on all sides - 29 => 202, - 31 => 206, - 45 => 202, - 46 => 203, - 47 => 206, - 55 => 185, - 59 => 204, - 63 => 203, - 87 => 185, - 126 => 203, - 143 => 206, - 77 => 202, - 171 => 204, - 187 => 204, - 215 => 185, - 190 => 203, - 237 => 202, - 30 => 203, - 110 => 203, - 111 => 206, - 119 => 185, - 142 => 203, - 158 => 203, - 235 => 204, - 93 => 202, - 109 => 202, - 94 => 203, - 174 => 203, - 159 => 206, - 221 => 202, - 157 => 202, - 79 => 206, - 95 => 185, - 23 => 185, // NSW and NSE + 1 diagonal - 39 => 185, - 71 => 185, - 103 => 185, - 135 => 185, - 151 => 185, - 199 => 185, - 78 => 203, - 27 => 204, - 43 => 204, - 75 => 204, - 107 => 204, - 139 => 204, - 155 => 204, - 173 => 202, - 141 => 202, - 205 => 202, - 175 => 204, - 203 => 204, - 61 => 205, // NEW cases - 125 => 205, // NEW cases - 189 => 205, // NEW cases - 206 => 205, - 207 => 202, - 222 => 205, - 238 => 205, - 253 => 205, - 254 => 205, - 167 => 186, // NSW, NW, SW - 91 => 186, // NSE, NE, SE - 183 => 186, // NSW, NW, SW, NE - 123 => 186, // NSE, NE, SE, NW - 231 => 186, // NSW, NW, SW, SE - 219 => 186, // NSE, NE, SE, SW - 247 => 186, - 251 => 186, - 127 => 187, // Everything except NE - 191 => 201, // Everything except NW - 223 => 188, // Everything except SE - 239 => 200, // Everything except SW - _ => 35, // We missed one? - } -} - pub fn render_debug_map(map: &Map, ctx: &mut Rltk) { let player_pos = Point::new(map.width / 2, map.height / 2); let (x_chars, y_chars) = ctx.get_char_size(); @@ -363,7 +116,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) = get_tile_glyph(idx, &*map); + let (glyph, fg, bg) = crate::map::themes::get_tile_glyph(idx, &*map); ctx.set(x, y, fg, bg, glyph); } } else if SHOW_BOUNDARIES { diff --git a/src/map/mod.rs b/src/map/mod.rs index 50f2aab..33e3139 100644 --- a/src/map/mod.rs +++ b/src/map/mod.rs @@ -4,6 +4,7 @@ use specs::prelude::*; use std::collections::HashSet; mod tiletype; pub use tiletype::{tile_cost, tile_opaque, tile_walkable, TileType}; +pub mod themes; // 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. diff --git a/src/map/themes.rs b/src/map/themes.rs new file mode 100644 index 0000000..7ff2b07 --- /dev/null +++ b/src/map/themes.rs @@ -0,0 +1,248 @@ +use super::{Map, TileType}; +use rltk::RGB; +use std::ops::{Add, Mul}; + +pub fn offset(rgb: rltk::RGB, offsets: (f32, f32, f32)) -> RGB { + let r = rgb.r * offsets.0; + let g = rgb.g * offsets.1; + let b = rgb.b * offsets.2; + + return rltk::RGB::from_f32(r, g, b); +} + +pub fn get_tile_glyph(idx: usize, map: &Map) -> (rltk::FontCharType, RGB, RGB) { + let offsets = map.colour_offset[idx]; + let glyph: rltk::FontCharType; + let mut fg: RGB = RGB::new(); + let mut bg: RGB; + + let default_bg: RGB = RGB::from_u8(39, 67, 67); + + match map.tiles[idx] { + TileType::Floor => { + glyph = rltk::to_cp437('.'); + fg = RGB::from_f32(0.1, 0.8, 0.5); + bg = default_bg; + } + TileType::WoodFloor => { + glyph = rltk::to_cp437('.'); + bg = RGB::from_u8(48, 43, 40); + } + TileType::Fence => { + glyph = rltk::to_cp437('='); + fg = RGB::from_u8(99, 48, 9); + bg = RGB::from_u8(48, 43, 33); + } + TileType::Wall => { + let x = idx as i32 % map.width; + let y = idx as i32 / map.width; + glyph = wall_glyph(&*map, x, y); + fg = RGB::from_f32(0.9, 0.75, 0.37); + bg = default_bg; + } + TileType::DownStair => { + glyph = rltk::to_cp437('>'); + fg = RGB::from_u8(200, 200, 0); + bg = default_bg; + } + TileType::Bridge => { + glyph = rltk::to_cp437('.'); + fg = default_bg; + bg = default_bg; + } + TileType::Gravel => { + glyph = rltk::to_cp437(';'); + bg = RGB::from_u8(39, 39, 54); + } + TileType::Road => { + glyph = rltk::to_cp437('~'); + //fg = RGB::from_u8(112, 105, 94); + bg = RGB::from_u8(29, 45, 46); + } + TileType::Grass => { + glyph = rltk::to_cp437('"'); + bg = RGB::from_u8(39, 67, 39); + } + TileType::Foliage => { + glyph = rltk::to_cp437(':'); + bg = RGB::from_u8(35, 62, 36); + } + TileType::HeavyFoliage => { + glyph = rltk::to_cp437(';'); + bg = RGB::from_u8(32, 62, 32); + } + TileType::Sand => { + glyph = rltk::to_cp437('.'); + bg = RGB::from_u8(92, 92, 66); + } + TileType::ShallowWater => { + glyph = rltk::to_cp437('~'); + bg = RGB::from_u8(51, 63, 91); + } + TileType::DeepWater => { + glyph = rltk::to_cp437('~'); + bg = RGB::from_u8(36, 45, 61); + } + } + if map.bloodstains.contains(&idx) { + bg = bg.add(RGB::from_f32(0.6, 0., 0.)); + } + + // If the foreground hasn't been changed, just add + // the bg to it. Otherwise, leave it as is. + if fg == RGB::new() { + fg = fg.add(bg).add(map.additional_fg_offset).add(map.additional_fg_offset); + } + + fg = offset(fg, offsets); + bg = offset(bg, offsets); + + if !map.visible_tiles[idx] { + fg = fg.mul(0.7); + bg = bg.mul(0.7); + } + + return (glyph, fg, bg); +} + +fn is_revealed_and_wall(map: &Map, x: i32, y: i32) -> bool { + let idx = map.xy_idx(x, y); + map.tiles[idx] == TileType::Wall && map.revealed_tiles[idx] +} + +fn wall_glyph(map: &Map, x: i32, y: i32) -> rltk::FontCharType { + if x < 1 || x > map.width - 2 || y < 1 || y > map.height - 2 as i32 { + return 35; + } + let mut mask: u8 = 0; + let diagonals_matter: Vec = vec![7, 11, 13, 14, 15]; + + if is_revealed_and_wall(map, x, y - 1) { + // N + mask += 1; + } + if is_revealed_and_wall(map, x, y + 1) { + // S + mask += 2; + } + if is_revealed_and_wall(map, x - 1, y) { + // W + mask += 4; + } + if is_revealed_and_wall(map, x + 1, y) { + // E + mask += 8; + } + + if diagonals_matter.contains(&mask) { + if is_revealed_and_wall(map, x + 1, y - 1) { + // Top right + mask += 16; + } + if is_revealed_and_wall(map, x - 1, y - 1) { + // Top left + mask += 32; + } + if is_revealed_and_wall(map, x + 1, y + 1) { + // Bottom right + mask += 64; + } + if is_revealed_and_wall(map, x - 1, y + 1) { + // Bottom left + mask += 128; + } + } + + match mask { + 0 => 254, // ■ (254) square pillar; but maybe ○ (9) looks better + 1 => 186, // Wall only to the north + 2 => 186, // Wall only to the south + 3 => 186, // Wall to the north and south + 4 => 205, // Wall only to the west + 5 => 188, // Wall to the north and west + 6 => 187, // Wall to the south and west + 7 => 185, // Wall to the north, south and west + 8 => 205, // Wall only to the east + 9 => 200, // Wall to the north and east + 10 => 201, // Wall to the south and east + 11 => 204, // Wall to the north, south and east + 12 => 205, // Wall to the east and west + 13 => 202, // Wall to the east, west, and north + 14 => 203, // Wall to the east, west, and south + 15 => 206, // ╬ Wall on all sides + 29 => 202, + 31 => 206, + 45 => 202, + 46 => 203, + 47 => 206, + 55 => 185, + 59 => 204, + 63 => 203, + 87 => 185, + 126 => 203, + 143 => 206, + 77 => 202, + 171 => 204, + 187 => 204, + 215 => 185, + 190 => 203, + 237 => 202, + 30 => 203, + 110 => 203, + 111 => 206, + 119 => 185, + 142 => 203, + 158 => 203, + 235 => 204, + 93 => 202, + 109 => 202, + 94 => 203, + 174 => 203, + 159 => 206, + 221 => 202, + 157 => 202, + 79 => 206, + 95 => 185, + 23 => 185, // NSW and NSE + 1 diagonal + 39 => 185, + 71 => 185, + 103 => 185, + 135 => 185, + 151 => 185, + 199 => 185, + 78 => 203, + 27 => 204, + 43 => 204, + 75 => 204, + 107 => 204, + 139 => 204, + 155 => 204, + 173 => 202, + 141 => 202, + 205 => 202, + 175 => 204, + 203 => 204, + 61 => 205, // NEW cases + 125 => 205, // NEW cases + 189 => 205, // NEW cases + 206 => 205, + 207 => 202, + 222 => 205, + 238 => 205, + 253 => 205, + 254 => 205, + 167 => 186, // NSW, NW, SW + 91 => 186, // NSE, NE, SE + 183 => 186, // NSW, NW, SW, NE + 123 => 186, // NSE, NE, SE, NW + 231 => 186, // NSW, NW, SW, SE + 219 => 186, // NSE, NE, SE, SW + 247 => 186, + 251 => 186, + 127 => 187, // Everything except NE + 191 => 201, // Everything except NW + 223 => 188, // Everything except SE + 239 => 200, // Everything except SW + _ => 35, // We missed one? + } +} diff --git a/src/map/tiletype.rs b/src/map/tiletype.rs index 8f19c9a..503173c 100644 --- a/src/map/tiletype.rs +++ b/src/map/tiletype.rs @@ -13,6 +13,8 @@ pub enum TileType { Gravel, Road, Grass, + Foliage, + HeavyFoliage, Sand, ShallowWater, Bridge, @@ -27,6 +29,8 @@ pub fn tile_walkable(tt: TileType) -> bool { | TileType::Gravel | TileType::Road | TileType::Grass + | TileType::Foliage + | TileType::HeavyFoliage | TileType::Sand | TileType::ShallowWater | TileType::Bridge diff --git a/src/map_builders/town.rs b/src/map_builders/town.rs index 65adb5b..d5a6a43 100644 --- a/src/map_builders/town.rs +++ b/src/map_builders/town.rs @@ -1,7 +1,7 @@ use super::{BuilderChain, BuilderMap, InitialMapBuilder, Position, TileType}; use std::collections::HashSet; -pub fn town_builder(new_depth: i32, rng: &mut rltk::RandomNumberGenerator, width: i32, height: i32) -> BuilderChain { +pub fn town_builder(new_depth: i32, _rng: &mut rltk::RandomNumberGenerator, width: i32, height: i32) -> BuilderChain { let mut chain = BuilderChain::new(new_depth, width, height); chain.start_with(TownBuilder::new()); @@ -143,8 +143,10 @@ impl TownBuilder { } build_data.take_snapshot(); + pier_idxs.push(build_data.map.xy_idx(largest_water_width + sand_width, y)); pier_idxs.push(build_data.map.xy_idx(largest_water_width + sand_width, y + 1)); pier_idxs.push(build_data.map.xy_idx(largest_water_width + sand_width, y + 2)); + pier_idxs.push(build_data.map.xy_idx(largest_water_width + sand_width, y + 3)); } return pier_idxs; @@ -176,7 +178,12 @@ impl TownBuilder { for x in OFFSET_FROM_LEFT + 1..build_data.width - BORDER { let gravel_idx = build_data.map.xy_idx(x, y); - build_data.map.tiles[gravel_idx] = TileType::Sand; + let roll = rng.roll_dice(1, 6); + match roll { + 1 => build_data.map.tiles[gravel_idx] = TileType::Foliage, + 2 => build_data.map.tiles[gravel_idx] = TileType::HeavyFoliage, + _ => {} + } if y > BORDER + 1 && y < build_data.height - BORDER - 1 && x > OFFSET_FROM_LEFT + 2 @@ -333,7 +340,7 @@ impl TownBuilder { for r in roads.iter() { nearest_tiletype.push(( *r, - rltk::DistanceAlg::PythagorasSquared.distance2d( + rltk::DistanceAlg::Manhattan.distance2d( tile_pt, rltk::Point::new(*r as i32 % build_data.map.width, *r as i32 / build_data.map.width), ),