From a8500b96d2b0c07f437ba6df2ae0abc8a5ef0251 Mon Sep 17 00:00:00 2001 From: Alex Page Date: Thu, 27 Jan 2022 01:51:09 -0500 Subject: [PATCH] Move GameState to its own module --- src/main.rs | 188 +++++++-------------------------------------------- src/state.rs | 154 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 178 insertions(+), 164 deletions(-) create mode 100644 src/state.rs diff --git a/src/main.rs b/src/main.rs index 51ab77b..17ebc40 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,162 +7,25 @@ pub mod resources; mod sidebar; mod sound; mod sound_effects; +mod state; pub mod systems; pub mod vga_color; use bracket_lib::prelude::*; use components::{ - monster::{color_for_kind, damage_for_kind, glyphs_for_kind, ticks_for_kind, MonsterKind}, + monster::{color_for_kind, glyphs_for_kind, ticks_for_kind, MonsterKind}, Monster, Player, Position, Renderable, }; -use constants::*; use map::{Map, TileType}; use resources::{Clock, LevelNumber, ShowDebugInfo, Stats}; use sound::SoundSystem; use sound_effects::SoundEffects; use specs::prelude::*; -use std::time::{Duration, Instant}; -use systems::MonsterMotion; +use state::State; +use std::time::Instant; + use vga_color as vga; -struct State { - ecs: World, -} - -fn try_move_player(delta_x: i32, delta_y: i32, ecs: &mut World) { - let entities = ecs.entities(); - let mut positions = ecs.write_storage::(); - let mut players = ecs.write_storage::(); - let mut map = ecs.write_resource::(); - let mut stats = ecs.write_resource::(); - let mut sound_system = ecs.write_resource::(); - - 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 = ecs.fetch_mut::(); - - 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) = - ecs.read_component::().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 = ecs.write_resource::(); - player_pos.x = pos.x; - player_pos.y = pos.y; - - ecs.write_resource::().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 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); - } - VirtualKeyCode::U | VirtualKeyCode::Home => try_move_player(-1, -1, &mut gs.ecs), - VirtualKeyCode::Up | VirtualKeyCode::I => { - try_move_player(0, -1, &mut gs.ecs); - } - VirtualKeyCode::O | VirtualKeyCode::PageUp => try_move_player(1, -1, &mut gs.ecs), - VirtualKeyCode::Right | VirtualKeyCode::K => { - try_move_player(1, 0, &mut gs.ecs); - } - VirtualKeyCode::Comma | VirtualKeyCode::PageDown => try_move_player(1, 1, &mut gs.ecs), - VirtualKeyCode::Down | VirtualKeyCode::M => { - try_move_player(0, 1, &mut gs.ecs); - } - VirtualKeyCode::N | VirtualKeyCode::End => try_move_player(-1, 1, &mut gs.ecs), - VirtualKeyCode::S => { - let mut sound_system = gs.ecs.write_resource::(); - let sound_effects = gs.ecs.fetch::(); - sound_system.play_sound(sound_effects.pickup.clone()); - } - VirtualKeyCode::D => { - let mut show_debug_info = gs.ecs.write_resource::(); - show_debug_info.0 = !show_debug_info.0; - } - VirtualKeyCode::Escape => { - ctx.quit(); - } - _ => { - let mut sound_system = gs.ecs.write_resource::(); - let sound_effects = gs.ecs.fetch::(); - sound_system.play_sound(sound_effects.bad_key.clone()); - } - }, - } -} - -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 mm = MonsterMotion {}; - mm.run_now(&self.ecs); - self.ecs.maintain(); - self.ecs.write_resource::().try_tick(); - } -} - fn main() -> BError { let context = BTermBuilder::simple(80, 25)? .with_fps_cap(60.0) @@ -174,18 +37,18 @@ fn main() -> BError { let sound_effects = SoundEffects::new(&ss); ss.play_sound(sound_effects.startup.clone()); - let mut gs = State { ecs: World::new() }; + let mut ecs = World::new(); - gs.ecs.insert(ss); - gs.ecs.insert(LevelNumber(0)); - gs.ecs.insert(ShowDebugInfo(false)); - gs.ecs.insert(Clock { + ecs.insert(ss); + ecs.insert(LevelNumber(0)); + ecs.insert(ShowDebugInfo(false)); + ecs.insert(Clock { last_ticked: Instant::now(), has_ticked: false, ticks: 0, }); - gs.ecs.insert(sound_effects); - gs.ecs.insert(Stats { + ecs.insert(sound_effects); + ecs.insert(Stats { score: 1290, gems: 14, whips: 7, @@ -193,10 +56,10 @@ fn main() -> BError { keys: 0, }); - gs.ecs.register::(); - gs.ecs.register::(); - gs.ecs.register::(); - gs.ecs.register::(); + ecs.register::(); + ecs.register::(); + ecs.register::(); + ecs.register::(); let mut map = Map::new(); let mut rng = RandomNumberGenerator::new(); @@ -204,8 +67,7 @@ fn main() -> BError { if rng.roll_dice(1, 16) < 2 && *tile == TileType::Floor { let position = map.index_to_point2d(i); let kind = MonsterKind::Slow; - gs.ecs - .create_entity() + ecs.create_entity() .with(Position { x: position.x, y: position.y, @@ -224,9 +86,9 @@ fn main() -> BError { } { - let entities = gs.ecs.entities(); - let positions = gs.ecs.read_storage::(); - let monsters = gs.ecs.read_storage::(); + let entities = ecs.entities(); + let positions = ecs.read_storage::(); + let monsters = ecs.read_storage::(); for (entity, _monster, pos) in (&entities, &monsters, &positions).join() { map.set_tile_at(Point { x: pos.x, y: pos.y }, TileType::Monster(entity)); @@ -235,8 +97,7 @@ fn main() -> BError { let player_start_pos = Point { x: 40, y: 22 }; - gs.ecs - .create_entity() + ecs.create_entity() .with(Position { x: player_start_pos.x, y: player_start_pos.y, @@ -253,10 +114,9 @@ fn main() -> BError { map.set_tile_at(player_start_pos, TileType::Player); - gs.ecs.insert(map); + ecs.insert(map); - gs.ecs - .insert(Point::new(player_start_pos.x, player_start_pos.y)); + ecs.insert(Point::new(player_start_pos.x, player_start_pos.y)); // for i in 0..10 { // gs.ecs @@ -298,5 +158,5 @@ fn main() -> BError { // let _ = gs.sound_system.play_sound(effect); - main_loop(context, gs) + main_loop(context, State::new(ecs)) } diff --git a/src/state.rs b/src/state.rs new file mode 100644 index 0000000..94d385c --- /dev/null +++ b/src/state.rs @@ -0,0 +1,154 @@ +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.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 { + 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::(); + let sound_effects = self.ecs.fetch::(); + sound_system.play_sound(sound_effects.pickup.clone()); + } + VirtualKeyCode::D => { + let mut show_debug_info = self.ecs.write_resource::(); + show_debug_info.0 = !show_debug_info.0; + } + VirtualKeyCode::Escape => { + ctx.quit(); + } + _ => { + let mut sound_system = self.ecs.write_resource::(); + let sound_effects = self.ecs.fetch::(); + 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::(); + let mut players = self.ecs.write_storage::(); + let mut map = self.ecs.write_resource::(); + let mut stats = self.ecs.write_resource::(); + let mut sound_system = self.ecs.write_resource::(); + + 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::(); + + 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::().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::(); + player_pos.x = pos.x; + player_pos.y = pos.y; + + self.ecs.write_resource::().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::().try_tick(); + } +}