#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] use bracket_lib::prelude::*; use components::{LeftMover, Player, Position, Renderable}; use constants::{MAP_HEIGHT, MAP_WIDTH, MAP_X, MAP_Y}; use map::{Map, TileType}; use resources::LevelNumber; use sound::SoundSystem; use sound_effects::SoundEffects; use specs::prelude::*; use std::time::{Duration, Instant}; use systems::LeftWalker; use vga_color as vga; pub mod components; pub mod constants; mod map; pub mod resources; mod sidebar; mod sound; mod sound_effects; pub mod systems; pub mod vga_color; struct State { ecs: World, sound_system: SoundSystem, } fn try_move_player(delta_x: i32, delta_y: i32, ecs: &mut World, sound_system: &mut SoundSystem) { let mut positions = ecs.write_storage::(); let mut players = ecs.write_storage::(); let map = ecs.fetch::(); for (player, pos) in (&mut players, &mut positions).join() { let now = Instant::now(); if now - player.last_moved > Duration::from_secs_f32(0.15) { let destination_x = pos.x + delta_x; let destination_y = pos.y + delta_y; let mut sound_effects = ecs.fetch_mut::(); if destination_x < 0 || (destination_x as usize) >= MAP_WIDTH || destination_y < 0 || (destination_y as usize) >= MAP_HEIGHT { let static_sound = sound_effects.get_new_static_effect(sound_system); sound_system.play_sound(static_sound); player.last_moved = now; continue; } let destination_tile = map.tile_at(destination_x as usize, destination_y as usize); if destination_tile != TileType::Wall { pos.x = destination_x; pos.y = destination_y; let step_sound = sound_effects.step.clone(); sound_system.play_sound(step_sound); } else { let blocked_sound = sound_effects.blocked.clone(); sound_system.play_sound(blocked_sound); } player.last_moved = now; } } } fn player_input(gs: &mut State, ctx: &mut BTerm) { // Player movement match ctx.key { None => {} // Nothing happened Some(key) => match key { VirtualKeyCode::Left | VirtualKeyCode::J => { try_move_player(-1, 0, &mut gs.ecs, &mut gs.sound_system); } VirtualKeyCode::U | VirtualKeyCode::Home => { try_move_player(-1, -1, &mut gs.ecs, &mut gs.sound_system) } VirtualKeyCode::Up | VirtualKeyCode::I => { try_move_player(0, -1, &mut gs.ecs, &mut gs.sound_system); } VirtualKeyCode::O | VirtualKeyCode::PageUp => { try_move_player(1, -1, &mut gs.ecs, &mut gs.sound_system) } VirtualKeyCode::Right | VirtualKeyCode::K => { try_move_player(1, 0, &mut gs.ecs, &mut gs.sound_system); } VirtualKeyCode::Comma | VirtualKeyCode::PageDown => { try_move_player(1, 1, &mut gs.ecs, &mut gs.sound_system) } VirtualKeyCode::Down | VirtualKeyCode::M => { try_move_player(0, 1, &mut gs.ecs, &mut gs.sound_system); } VirtualKeyCode::N | VirtualKeyCode::End => { try_move_player(-1, 1, &mut gs.ecs, &mut gs.sound_system) } VirtualKeyCode::S => { let sound_effects = gs.ecs.fetch::(); let pickup_sound = sound_effects.pickup.clone(); gs.sound_system.play_sound(pickup_sound); } VirtualKeyCode::Escape => { ctx.quit(); } _ => { let sound_effects = gs.ecs.fetch::(); let bad_key_sound = sound_effects.bad_key.clone(); gs.sound_system.play_sound(bad_key_sound); } }, } } impl GameState for State { fn tick(&mut self, ctx: &mut BTerm) { ctx.cls(); player_input(self, ctx); self.run_systems(); let map = self.ecs.fetch::(); map.draw(ctx); let positions = self.ecs.read_storage::(); let renderables = self.ecs.read_storage::(); for (pos, render) in (&positions, &renderables).join() { ctx.set( pos.x + MAP_X as i32, pos.y + MAP_Y as i32, render.fg, render.bg, render.glyph, ); } sidebar::draw(&self.ecs, ctx); } } impl State { fn run_systems(&mut self) { let mut lw = LeftWalker {}; lw.run_now(&self.ecs); self.ecs.maintain(); } } fn main() -> BError { let context = BTermBuilder::simple(80, 25)? .with_fps_cap(60.0) .with_title("Kroz") .with_tile_dimensions(8, 16) .build()?; let mut ss = SoundSystem::new(); let sound_effects = SoundEffects::new(&ss); ss.play_sound(sound_effects.startup.clone()); let mut gs = State { ecs: World::new(), sound_system: ss, }; gs.ecs.insert(LevelNumber(0)); gs.ecs.insert(sound_effects); gs.ecs.insert(Map::new()); gs.ecs.register::(); gs.ecs.register::(); gs.ecs.register::(); gs.ecs.register::(); gs.ecs .create_entity() .with(Position { x: 40, y: 22 }) .with(Renderable { glyph: to_cp437('☻'), fg: RGB::named(vga::YELLOW_BRIGHT), bg: RGB::named(vga::BLACK), }) .with(Player { last_moved: Instant::now(), score: 1290, gems: 14, whips: 7, teleports: 0, keys: 0, }) .build(); // 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| { // (1..10).rev().flat_map(move |y| { // vec![Sound { // sound_type: SoundType::Tone(x * y * y), // duration: Duration::from_millis((y as f64 / 1.5) as u64), // }] // }) // }) // .collect(); // let descent_effect = gs.sound_system.render_sound_effect(SoundEffect { // sounds: descent_sounds, // }); // 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, gs) }