kroz-rs/src/main.rs

235 lines
7.1 KiB
Rust

#![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::<Position>();
let mut players = ecs.write_storage::<Player>();
let map = ecs.fetch::<Map>();
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::<SoundEffects>();
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::<SoundEffects>();
let pickup_sound = sound_effects.pickup.clone();
gs.sound_system.play_sound(pickup_sound);
}
VirtualKeyCode::Escape => {
ctx.quit();
}
_ => {
let sound_effects = gs.ecs.fetch::<SoundEffects>();
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>();
map.draw(ctx);
let positions = self.ecs.read_storage::<Position>();
let renderables = self.ecs.read_storage::<Renderable>();
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::<Position>();
gs.ecs.register::<Renderable>();
gs.ecs.register::<LeftMover>();
gs.ecs.register::<Player>();
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<Sound> = (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)
}