154 lines
5.7 KiB
Rust
154 lines
5.7 KiB
Rust
use std::time::{Duration, Instant};
|
|
|
|
use crate::components::monster::damage_for_kind;
|
|
use crate::components::{Monster, Player, Position, Renderable};
|
|
use crate::map::{Map, TileType};
|
|
use crate::resources::{Clock, ShowDebugInfo, Stats};
|
|
use crate::sound::SoundSystem;
|
|
use crate::sound_effects::SoundEffects;
|
|
use crate::systems::MonsterMotion;
|
|
use crate::{constants::*, sidebar};
|
|
use bracket_lib::prelude::*;
|
|
use specs::prelude::*;
|
|
|
|
pub struct State {
|
|
ecs: World,
|
|
}
|
|
|
|
impl GameState for State {
|
|
fn tick(&mut self, ctx: &mut BTerm) {
|
|
ctx.cls();
|
|
|
|
self.handle_input(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 {
|
|
pub fn new(ecs: World) -> Self {
|
|
State { ecs }
|
|
}
|
|
|
|
fn handle_input(&mut self, ctx: &mut BTerm) {
|
|
// Player movement
|
|
match ctx.key {
|
|
None => {} // Nothing happened
|
|
Some(key) => match key {
|
|
VirtualKeyCode::Left | VirtualKeyCode::J => {
|
|
self.try_move_player(-1, 0);
|
|
}
|
|
VirtualKeyCode::U | VirtualKeyCode::Home => self.try_move_player(-1, -1),
|
|
VirtualKeyCode::Up | VirtualKeyCode::I => {
|
|
self.try_move_player(0, -1);
|
|
}
|
|
VirtualKeyCode::O | VirtualKeyCode::PageUp => self.try_move_player(1, -1),
|
|
VirtualKeyCode::Right | VirtualKeyCode::K => {
|
|
self.try_move_player(1, 0);
|
|
}
|
|
VirtualKeyCode::Comma | VirtualKeyCode::PageDown => self.try_move_player(1, 1),
|
|
VirtualKeyCode::Down | VirtualKeyCode::M => {
|
|
self.try_move_player(0, 1);
|
|
}
|
|
VirtualKeyCode::N | VirtualKeyCode::End => self.try_move_player(-1, 1),
|
|
VirtualKeyCode::S => {
|
|
let mut sound_system = self.ecs.write_resource::<SoundSystem>();
|
|
let sound_effects = self.ecs.fetch::<SoundEffects>();
|
|
sound_system.play_sound(sound_effects.pickup.clone());
|
|
}
|
|
VirtualKeyCode::D => {
|
|
let mut show_debug_info = self.ecs.write_resource::<ShowDebugInfo>();
|
|
show_debug_info.0 = !show_debug_info.0;
|
|
}
|
|
VirtualKeyCode::Escape => {
|
|
ctx.quit();
|
|
}
|
|
_ => {
|
|
let mut sound_system = self.ecs.write_resource::<SoundSystem>();
|
|
let sound_effects = self.ecs.fetch::<SoundEffects>();
|
|
sound_system.play_sound(sound_effects.bad_key.clone());
|
|
}
|
|
},
|
|
}
|
|
}
|
|
|
|
fn try_move_player(&mut self, delta_x: i32, delta_y: i32) {
|
|
let entities = self.ecs.entities();
|
|
let mut positions = self.ecs.write_storage::<Position>();
|
|
let mut players = self.ecs.write_storage::<Player>();
|
|
let mut map = self.ecs.write_resource::<Map>();
|
|
let mut stats = self.ecs.write_resource::<Stats>();
|
|
let mut sound_system = self.ecs.write_resource::<SoundSystem>();
|
|
|
|
for (player, pos) in (&mut players, &mut positions).join() {
|
|
let now = Instant::now();
|
|
if now - player.last_moved > Duration::from_secs_f32(PLAYER_STEP_PERIOD) {
|
|
let destination = Point {
|
|
x: pos.x + delta_x,
|
|
y: pos.y + delta_y,
|
|
};
|
|
|
|
let mut sound_effects = self.ecs.fetch_mut::<SoundEffects>();
|
|
|
|
if map.in_bounds(destination) {
|
|
if map.is_solid(destination) {
|
|
sound_system.play_sound(sound_effects.blocked.clone());
|
|
} else {
|
|
if let TileType::Monster(monster) = map.get_tile_at(destination) {
|
|
if let Some(monster_component) =
|
|
self.ecs.read_component::<Monster>().get(monster)
|
|
{
|
|
if stats.gems > 0 {
|
|
stats.gems -= damage_for_kind(monster_component.kind);
|
|
}
|
|
let _ = entities.delete(monster);
|
|
}
|
|
}
|
|
map.set_tile_at(Point { x: pos.x, y: pos.y }, TileType::Floor);
|
|
map.set_tile_at(destination, TileType::Player);
|
|
|
|
pos.x = destination.x;
|
|
pos.y = destination.y;
|
|
|
|
let mut player_pos = self.ecs.write_resource::<Point>();
|
|
player_pos.x = pos.x;
|
|
player_pos.y = pos.y;
|
|
|
|
self.ecs.write_resource::<Clock>().force_tick();
|
|
|
|
sound_system.play_sound(sound_effects.step.clone());
|
|
}
|
|
} else {
|
|
let static_sound = sound_effects.get_new_static_effect(&sound_system);
|
|
sound_system.play_sound(static_sound);
|
|
}
|
|
|
|
player.last_moved = now;
|
|
}
|
|
}
|
|
}
|
|
|
|
fn run_systems(&mut self) {
|
|
let mut mm = MonsterMotion {};
|
|
mm.run_now(&self.ecs);
|
|
self.ecs.maintain();
|
|
self.ecs.write_resource::<Clock>().try_tick();
|
|
}
|
|
}
|