diff --git a/src/difficulty.rs b/src/difficulty.rs deleted file mode 100644 index 87add56..0000000 --- a/src/difficulty.rs +++ /dev/null @@ -1,45 +0,0 @@ -#[derive(Debug, Eq, PartialEq, Copy, Clone, Hash)] -pub struct Difficulty { - pub value: u32, - pub starting_gems: u32, - pub starting_whips: u32, - pub starting_teleports: u32, - pub starting_keys: u32, - pub starting_whip_power: u32, -} - -pub const SECRET: Difficulty = Difficulty { - value: 9, - starting_gems: 250, - starting_whips: 100, - starting_teleports: 50, - starting_keys: 1, - starting_whip_power: 3, -}; - -pub const NOVICE: Difficulty = Difficulty { - value: 8, - starting_gems: 20, - starting_whips: 10, - starting_teleports: 0, - starting_keys: 0, - starting_whip_power: 0, -}; - -pub const EXPERIENCED: Difficulty = Difficulty { - value: 5, - starting_gems: 15, - starting_whips: 0, - starting_teleports: 0, - starting_keys: 0, - starting_whip_power: 0, -}; - -pub const ADVANCED: Difficulty = Difficulty { - value: 2, - starting_gems: 10, - starting_whips: 0, - starting_teleports: 0, - starting_keys: 0, - starting_whip_power: 0, -}; diff --git a/src/levels.rs b/src/levels.rs deleted file mode 100644 index a0039b6..0000000 --- a/src/levels.rs +++ /dev/null @@ -1,56 +0,0 @@ -use std::collections::HashMap; - -use crate::{constants::*, tile_data::TileType}; - -#[allow(clippy::large_enum_variant)] -pub enum Level { - Normal([&'static str; MAP_HEIGHT]), - Randomized(HashMap), - End, -} - -pub fn get_level(index: u32) -> Level { - match index { - 0 => Level::Randomized(HashMap::from([ - (TileType::Slow, 15), - (TileType::Whip, 1), - (TileType::Stairs, 3), - (TileType::Gem, 8), - ])), - 1 => Level::Normal([ - "LXXX2 2 2 2 2 2 2 2 2 2 2 2 2 +", - "+XXX 2 2 2 2 2 2 2 2 XXX ", - " XXX2 2 2 2 2 2 2 2 2 2 2 XTX ", - "+XXX 2 2 2 2 2 2 2 XXX ", - " XXX 2 2 2 2 2 2 2 2 2 2 ", - "+XXX 2 ", - " XXX 2 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 2 2 ", - "+XXX2 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 2 ", - " XXX 2 XXX2 W 2XXX 2 ", - "+XXX 2 XXX 2 FFFFF 2 XXX 2 2 ", - " XXX2 2 XXX F111F XXX ", - "+XXX2 XXX+ 3 3 W F1P1F W 3 3 +XXX 2 ", - "XXXX 2 XXX F111F XXX 2 2", - "WXXX 2 XXX 2 FFFFF 2 XXX 2 ", - "WXXX2 XXX2 W 2XXX 2 ", - "WXXX 2 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 2 ", - "WXXX 2 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 2 ", - "WXXX2 2 ", - "WXXX 2 2 2 2 2 2 2 2 2 2 2 ", - "XXXX 2 2 2 2 2 2 2 2 2 2 2 XXX ", - "XXXX2 2 2 2 2 2 2 2 2 2 2 2 XTX ", - "XXXX 2 2 2 2 2 2 2 2 2 2 2 2 XXX ", - "CXXX 2 2 2 2 2 2 2 2 2 2 2 2 2 2 +", - ]), - 2 => Level::Randomized(HashMap::from([ - (TileType::Slow, 60), - (TileType::Block, 25), - (TileType::Whip, 5), - (TileType::Stairs, 2), - (TileType::Gem, 10), - (TileType::Teleport, 3), - ])), - 40 => Level::End, - _ => Level::Randomized(HashMap::new()), - } -} diff --git a/src/main.rs b/src/main.rs index 344cc9d..136d7d9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,8 +2,6 @@ pub mod components; pub mod constants; -pub mod difficulty; -pub mod levels; pub mod resources; mod sidebar; mod state; @@ -12,27 +10,33 @@ pub mod tile_data; pub mod vga_color; use bracket_lib::prelude::*; -use components::{Monster, Player, Position, Renderable}; +use components::{ + monster::{color_for_kind, glyphs_for_kind, ticks_for_kind, MonsterKind}, + Monster, Player, Position, Renderable, +}; use resources::{Clock, LevelNumber, Map, ShowDebugInfo, SoundEffects, SoundOutput, Stats}; use specs::prelude::*; use state::State; use std::time::Instant; +use tile_data::TileType; + +use vga_color as vga; fn main() -> BError { - let context = BTermBuilder::vga(80, 25) + let context = BTermBuilder::simple(80, 25)? .with_fps_cap(60.0) .with_title("Kroz") + .with_tile_dimensions(8, 16) .build()?; - let mut sound_system = SoundOutput::new(); - let sound_effects = SoundEffects::new(&sound_system); - sound_system.play_sound(sound_effects.startup.clone()); + let mut ss = SoundOutput::new(); + let sound_effects = SoundEffects::new(&ss); + ss.play_sound(sound_effects.startup.clone()); let mut ecs = World::new(); - let starting_level = 0; - ecs.insert(sound_system); - ecs.insert(LevelNumber(starting_level)); + ecs.insert(ss); + ecs.insert(LevelNumber(0)); ecs.insert(ShowDebugInfo(false)); ecs.insert(Clock { last_ticked: Instant::now(), @@ -40,16 +44,12 @@ fn main() -> BError { ticks: 0, }); ecs.insert(sound_effects); - - let selected_difficulty = difficulty::SECRET; - ecs.insert(selected_difficulty); ecs.insert(Stats { - score: 0, - gems: selected_difficulty.starting_gems, - whips: selected_difficulty.starting_whips, - whip_power: selected_difficulty.starting_whip_power, - teleports: selected_difficulty.starting_teleports, - keys: selected_difficulty.starting_keys, + score: 1290, + gems: 14, + whips: 7, + teleports: 0, + keys: 0, }); ecs.register::(); @@ -57,10 +57,69 @@ fn main() -> BError { ecs.register::(); ecs.register::(); - let map = Map::from_level(levels::get_level(starting_level)); - map.spawn_entities(&mut ecs); + let map = Map::new(); + let mut rng = RandomNumberGenerator::new(); + for (i, tile) in &mut map.get_tiles().iter().enumerate() { + if rng.roll_dice(1, 16) < 2 && *tile == TileType::Floor { + let position = map.index_to_point2d(i); + let kind = match rng.range(0, 3) { + 0 => MonsterKind::Slow, + 1 => MonsterKind::Medium, + 2 => MonsterKind::Fast, + _ => MonsterKind::Slow, + }; + ecs.create_entity() + .with(Position { + x: position.x, + y: position.y, + }) + .with(Renderable { + glyph: *rng.random_slice_entry(&glyphs_for_kind(kind)).unwrap(), + fg: color_for_kind(kind), + bg: RGB::named(vga::BLACK), + }) + .with(Monster { + kind, + ticks_until_move: ticks_for_kind(kind), + }) + .build(); + } + } + + let player_start_pos = Point { x: 40, y: 22 }; + + ecs.create_entity() + .with(Position { + x: player_start_pos.x, + y: player_start_pos.y, + }) + .with(Renderable { + glyph: to_cp437('☻'), + fg: RGB::named(vga::YELLOW_BRIGHT), + bg: RGB::named(vga::BLACK), + }) + .with(Player { + last_moved: Instant::now(), + }) + .build(); + ecs.insert(map); + ecs.insert(Point::new(player_start_pos.x, player_start_pos.y)); + + // for i in 0..10 { + // gs.ecs + // .create_entity() + // .with(Position { x: i * 7, y: 20 }) + // .with(Renderable { + // glyph: to_cp437('Ä'), + // fg: RGB::named(vga::RED_BRIGHT), + // bg: RGB::named(vga::BLACK), + // }) + // .with(LeftMover {}) + // .build(); + // } + // let descent_sounds: Vec = (20..100) // .rev() // .flat_map(|x| { @@ -79,5 +138,14 @@ fn main() -> BError { // let _ = gs.sound_system.play_sound(descent_effect); + // let effect = gs.sound_system.render_sound_effect(SoundEffect { + // sounds: vec![Sound { + // sound_type: SoundType::Tone(3500), + // duration: Duration::from_millis(4000), + // }], + // }); + + // let _ = gs.sound_system.play_sound(effect); + main_loop(context, State::new(ecs)) } diff --git a/src/resources/map.rs b/src/resources/map.rs index d561306..3e72d57 100644 --- a/src/resources/map.rs +++ b/src/resources/map.rs @@ -1,21 +1,16 @@ -use std::time::Instant; - use crate::{ - components::{monster::*, Monster, Player, Position, Renderable}, - constants::*, - levels::Level, + constants::{MAP_HEIGHT, MAP_SIZE, MAP_WIDTH, MAP_X, MAP_Y}, tile_data::{self, TileType}, vga_color as vga, }; use bracket_lib::{prelude::*, random::RandomNumberGenerator}; -use specs::{Builder, Entity, World, WorldExt}; +use specs::Entity; pub struct Map { tiles: Vec, tile_content: Vec>, border_fg: RGB, border_bg: RGB, - gem_color: RGB, } impl BaseMap for Map {} @@ -34,135 +29,20 @@ impl Default for Map { impl Map { pub fn new() -> Self { + let mut tiles = vec![TileType::Floor; MAP_SIZE]; let mut rng = RandomNumberGenerator::new(); + for tile in &mut tiles { + if rng.roll_dice(1, 16) < 2 { + *tile = TileType::Wall; + } else if rng.roll_dice(1, 16) < 2 { + *tile = TileType::Block; + } + } Self { - tiles: vec![TileType::Floor; MAP_SIZE], + tiles, tile_content: vec![None; MAP_SIZE], border_fg: RGB::named(vga::get_by_index(rng.range(8, 15))), border_bg: RGB::named(vga::get_by_index(rng.range(1, 7) as usize)), - gem_color: RGB::named(vga::get_by_index(rng.range(1, 15))), - } - } - - pub fn from_level(level: Level) -> Self { - match level { - Level::Normal(_data) => todo!(), - Level::Randomized(data) => { - let mut rng = RandomNumberGenerator::new(); - let mut map = Self::new(); - for (tile, count) in data { - for _ in 0..count { - loop { - let point = Point { - x: rng.range(0, MAP_WIDTH as i32), - y: rng.range(0, MAP_HEIGHT as i32), - }; - if map.get_tile_at(point) == TileType::Floor { - map.set_tile_at(point, tile); - break; - } - } - } - } - loop { - let point = Point { - x: rng.range(0, MAP_WIDTH as i32), - y: rng.range(0, MAP_HEIGHT as i32), - }; - if map.get_tile_at(point) == TileType::Floor { - map.set_tile_at(point, TileType::Player); - break; - } - } - map - } - Level::End => todo!(), - } - } - - pub fn spawn_entities(&self, ecs: &mut World) { - for (index, tile) in self.tiles.iter().enumerate() { - let point = self.index_to_point2d(index); - match tile { - TileType::Player => { - ecs.create_entity() - .with(Position { - x: point.x, - y: point.y, - }) - .with(Renderable { - glyph: to_cp437('☻'), - fg: RGB::named(vga::YELLOW_BRIGHT), - bg: RGB::named(vga::BLACK), - }) - .with(Player { - last_moved: Instant::now(), - }) - .build(); - ecs.insert(point); - } - TileType::Slow => { - let mut rng = RandomNumberGenerator::new(); - ecs.create_entity() - .with(Position { - x: point.x, - y: point.y, - }) - .with(Renderable { - glyph: *rng - .random_slice_entry(&glyphs_for_kind(MonsterKind::Slow)) - .unwrap(), - fg: color_for_kind(MonsterKind::Slow), - bg: RGB::named(vga::BLACK), - }) - .with(Monster { - kind: MonsterKind::Slow, - ticks_until_move: ticks_for_kind(MonsterKind::Slow), - }) - .build(); - } - TileType::Medium => { - let mut rng = RandomNumberGenerator::new(); - ecs.create_entity() - .with(Position { - x: point.x, - y: point.y, - }) - .with(Renderable { - glyph: *rng - .random_slice_entry(&glyphs_for_kind(MonsterKind::Medium)) - .unwrap(), - fg: color_for_kind(MonsterKind::Medium), - bg: RGB::named(vga::BLACK), - }) - .with(Monster { - kind: MonsterKind::Medium, - ticks_until_move: ticks_for_kind(MonsterKind::Medium), - }) - .build(); - } - TileType::Fast => { - let mut rng = RandomNumberGenerator::new(); - ecs.create_entity() - .with(Position { - x: point.x, - y: point.y, - }) - .with(Renderable { - glyph: *rng - .random_slice_entry(&glyphs_for_kind(MonsterKind::Fast)) - .unwrap(), - fg: color_for_kind(MonsterKind::Fast), - bg: RGB::named(vga::BLACK), - }) - .with(Monster { - kind: MonsterKind::Fast, - ticks_until_move: ticks_for_kind(MonsterKind::Fast), - }) - .build(); - } - _ => {} - } } } @@ -206,11 +86,7 @@ impl Map { ctx.set( x + MAP_X, y + MAP_Y, - if *tile == TileType::Gem { - self.gem_color - } else { - RGB::named(data.color_fg) - }, + data.color_fg, data.color_bg, data.glyph, ); diff --git a/src/resources/mod.rs b/src/resources/mod.rs index 1a39908..330b80e 100644 --- a/src/resources/mod.rs +++ b/src/resources/mod.rs @@ -45,7 +45,6 @@ pub struct Stats { pub score: u32, pub gems: u32, pub whips: u32, - pub whip_power: u32, pub teleports: u32, pub keys: u32, } diff --git a/src/sidebar.rs b/src/sidebar.rs index 4e09acf..08f66b2 100644 --- a/src/sidebar.rs +++ b/src/sidebar.rs @@ -39,7 +39,7 @@ pub fn draw(ecs: &World, ctx: &mut BTerm) { ctx.print_centered_at( SIDEBAR_POS_X + 6, SIDEBAR_POS_Y + 4, - ecs.read_resource::().0 + 1, + ecs.read_resource::().0, ); ctx.print(SIDEBAR_POS_X + 4, SIDEBAR_POS_Y + 6, "Gems"); ctx.print(SIDEBAR_POS_X + 4, SIDEBAR_POS_Y + 9, "Whips"); diff --git a/src/tile_data.rs b/src/tile_data.rs index b9dba3a..6fe105d 100644 --- a/src/tile_data.rs +++ b/src/tile_data.rs @@ -8,14 +8,12 @@ pub struct TileData { pub color_fg: (u8, u8, u8), pub color_bg: (u8, u8, u8), pub serialized_char: char, + pub blink: bool, } -#[derive(Eq, PartialEq, Copy, Clone, Hash)] +#[derive(PartialEq, Copy, Clone)] pub enum TileType { Floor, // 0 - Slow, // 1 - Medium, // 2 - Fast, // 3 Block, // 4 Whip, // 5 Stairs, // 6 @@ -72,306 +70,336 @@ pub fn tile_data(tile: TileType) -> TileData { serialized_char: ' ', color_fg: vga::BLACK, color_bg: vga::BLACK, - }, - TileType::Slow => TileData { - glyph: 0, - serialized_char: '1', - color_fg: vga::BLACK, - color_bg: vga::BLACK, - }, - TileType::Medium => TileData { - glyph: 0, - serialized_char: '2', - color_fg: vga::BLACK, - color_bg: vga::BLACK, - }, - TileType::Fast => TileData { - glyph: 0, - serialized_char: '3', - color_fg: vga::BLACK, - color_bg: vga::BLACK, + blink: false, }, TileType::Block => TileData { glyph: to_cp437('▓'), serialized_char: 'X', color_fg: vga::YELLOW, color_bg: vga::BLACK, + blink: false, }, TileType::Whip => TileData { glyph: to_cp437('⌠'), serialized_char: 'W', color_fg: vga::WHITE_BRIGHT, color_bg: vga::BLACK, + blink: false, }, TileType::Stairs => TileData { glyph: to_cp437('≡'), serialized_char: 'L', color_fg: vga::BLACK, color_bg: vga::WHITE, + blink: true, }, TileType::Chest => TileData { glyph: to_cp437('C'), serialized_char: 'C', color_fg: vga::YELLOW_BRIGHT, color_bg: vga::RED, + blink: false, }, TileType::SlowTime => TileData { glyph: to_cp437('Φ'), serialized_char: 'S', color_fg: vga::CYAN_BRIGHT, color_bg: vga::BLACK, + blink: false, }, TileType::Gem => TileData { glyph: to_cp437('♦'), serialized_char: '+', color_fg: vga::WHITE, color_bg: vga::BLACK, + blink: false, }, TileType::Invisible => TileData { glyph: to_cp437('¡'), serialized_char: 'I', color_fg: vga::GREEN, color_bg: vga::BLACK, + blink: false, }, TileType::Teleport => TileData { glyph: to_cp437('↑'), serialized_char: 'T', color_fg: vga::MAGENTA_BRIGHT, color_bg: vga::BLACK, + blink: false, }, TileType::Key => TileData { glyph: to_cp437('î'), serialized_char: 'K', color_fg: vga::RED_BRIGHT, color_bg: vga::BLACK, + blink: false, }, TileType::Door => TileData { glyph: to_cp437('∞'), serialized_char: 'D', color_fg: vga::CYAN, color_bg: vga::MAGENTA, + blink: false, }, TileType::Wall => TileData { glyph: to_cp437('█'), serialized_char: '#', color_fg: vga::YELLOW, color_bg: vga::BLACK, + blink: false, }, TileType::SpeedTime => TileData { glyph: to_cp437('Θ'), serialized_char: 'F', color_fg: vga::CYAN_BRIGHT, color_bg: vga::BLACK, + blink: false, }, TileType::Trap => TileData { glyph: to_cp437('∙'), serialized_char: '.', color_fg: vga::WHITE, color_bg: vga::BLACK, + blink: false, }, TileType::River => TileData { glyph: to_cp437('≈'), serialized_char: 'R', color_fg: vga::BLUE_BRIGHT, color_bg: vga::BLUE, + blink: false, }, TileType::Power => TileData { glyph: to_cp437('○'), serialized_char: 'Q', color_fg: vga::WHITE_BRIGHT, color_bg: vga::BLACK, + blink: false, }, TileType::Forest => TileData { glyph: to_cp437('█'), serialized_char: '/', color_fg: vga::GREEN, color_bg: vga::BLACK, + blink: false, }, TileType::Tree => TileData { glyph: to_cp437('♣'), serialized_char: '\\', color_fg: vga::YELLOW, color_bg: vga::GREEN, + blink: false, }, TileType::Bomb => TileData { glyph: to_cp437('¥'), serialized_char: 'B', color_fg: vga::WHITE_BRIGHT, color_bg: vga::BLACK, + blink: false, }, TileType::Lava => TileData { glyph: to_cp437('▓'), serialized_char: 'V', color_fg: vga::RED_BRIGHT, color_bg: vga::RED, + blink: false, }, TileType::Pit => TileData { glyph: to_cp437('░'), serialized_char: '=', color_fg: vga::WHITE, color_bg: vga::BLACK, + blink: false, }, TileType::Tome => TileData { glyph: to_cp437('♀'), serialized_char: 'A', color_fg: vga::WHITE_BRIGHT, color_bg: vga::BLACK, + blink: true, }, TileType::Tunnel => TileData { glyph: to_cp437('∩'), serialized_char: 'U', color_fg: vga::WHITE_BRIGHT, color_bg: vga::BLACK, + blink: false, }, TileType::Freeze => TileData { glyph: to_cp437('ƒ'), serialized_char: 'Z', color_fg: vga::CYAN_BRIGHT, color_bg: vga::BLACK, + blink: false, }, TileType::Nugget => TileData { glyph: to_cp437('☼'), serialized_char: '*', color_fg: vga::YELLOW_BRIGHT, color_bg: vga::BLACK, + blink: false, }, TileType::Quake => TileData { glyph: 0, serialized_char: 'E', color_fg: vga::BLACK, color_bg: vga::BLACK, + blink: false, }, TileType::InvisibleBlock => TileData { glyph: 0, serialized_char: ';', color_fg: vga::BLACK, color_bg: vga::BLACK, + blink: false, }, TileType::InvisibleWall => TileData { glyph: 0, serialized_char: ':', color_fg: vga::BLACK, color_bg: vga::BLACK, + blink: false, }, TileType::InvisibleDoor => TileData { glyph: 0, serialized_char: '`', color_fg: vga::BLACK, color_bg: vga::BLACK, + blink: false, }, TileType::Stop => TileData { glyph: 0, serialized_char: '-', color_fg: vga::BLACK, color_bg: vga::BLACK, + blink: false, }, TileType::Zap => TileData { glyph: to_cp437('▲'), serialized_char: '%', color_fg: vga::RED_BRIGHT, color_bg: vga::BLACK, + blink: false, }, TileType::Create => TileData { glyph: to_cp437('▼'), serialized_char: ']', color_fg: vga::WHITE_BRIGHT, color_bg: vga::BLACK, + blink: false, }, TileType::Generator => TileData { glyph: to_cp437('♠'), serialized_char: 'G', color_fg: vga::BLACK, color_bg: vga::BLACK, + blink: false, }, TileType::Trap2 => TileData { glyph: 0, serialized_char: '@', color_fg: vga::BLACK, color_bg: vga::BLACK, + blink: false, }, TileType::Trap3 => TileData { glyph: 0, serialized_char: ')', color_fg: vga::BLACK, color_bg: vga::BLACK, + blink: false, }, TileType::Trap4 => TileData { glyph: 0, serialized_char: '(', color_fg: vga::BLACK, color_bg: vga::BLACK, + blink: false, }, TileType::Trap5 => TileData { glyph: 0, serialized_char: '$', // Unsure about this color_fg: vga::BLACK, color_bg: vga::BLACK, + blink: false, }, TileType::Trap6 => TileData { glyph: 0, serialized_char: 'α', color_fg: vga::BLACK, color_bg: vga::BLACK, + blink: false, }, TileType::Trap7 => TileData { glyph: 0, serialized_char: 'ß', color_fg: vga::BLACK, color_bg: vga::BLACK, + blink: false, }, TileType::Trap8 => TileData { glyph: 0, serialized_char: 'Γ', color_fg: vga::BLACK, color_bg: vga::BLACK, + blink: false, }, TileType::Trap9 => TileData { glyph: 0, serialized_char: 'π', color_fg: vga::BLACK, color_bg: vga::BLACK, + blink: false, }, TileType::Trap10 => TileData { glyph: 0, serialized_char: 'Σ', color_fg: vga::BLACK, color_bg: vga::BLACK, + blink: false, }, TileType::Trap11 => TileData { glyph: 0, serialized_char: 'σ', color_fg: vga::BLACK, color_bg: vga::BLACK, + blink: false, }, TileType::Trap12 => TileData { glyph: 0, serialized_char: 'µ', color_fg: vga::BLACK, color_bg: vga::BLACK, + blink: false, }, TileType::Trap13 => TileData { glyph: 0, serialized_char: 'τ', color_fg: vga::BLACK, color_bg: vga::BLACK, + blink: false, }, TileType::Player => TileData { - glyph: 0, + glyph: to_cp437('≡'), serialized_char: 'P', color_fg: vga::BLACK, - color_bg: vga::BLACK, + color_bg: vga::WHITE, + blink: true, }, TileType::Punctuation => TileData { glyph: to_cp437('!'), serialized_char: '!', color_fg: vga::WHITE_BRIGHT, color_bg: vga::YELLOW, + blink: false, }, TileType::Letter(c) => TileData { - glyph: to_cp437(c.to_ascii_uppercase()), + glyph: to_cp437(c), serialized_char: c, color_fg: vga::WHITE_BRIGHT, color_bg: vga::YELLOW, + blink: false, }, } }