diff --git a/src/components.rs b/src/components.rs index 7c00aae..317c01b 100644 --- a/src/components.rs +++ b/src/components.rs @@ -11,3 +11,12 @@ pub struct Player; #[derive(Clone, Copy, Debug, PartialEq)] pub struct Enemy; + +#[derive(Clone, Copy, Debug, PartialEq)] +pub struct MovingRandomly; + +#[derive(Clone, Copy, Debug, PartialEq)] +pub struct WantsToMove { + pub entity: Entity, + pub destination: Point, +} diff --git a/src/main.rs b/src/main.rs index 2059466..7f0aa7a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,6 +4,7 @@ mod map; mod map_builder; mod spawners; mod systems; +mod turn_state; mod prelude { pub use bracket_lib::prelude::*; @@ -20,13 +21,16 @@ mod prelude { pub use crate::map_builder::*; pub use crate::spawners::*; pub use crate::systems::*; + pub use crate::turn_state::*; } use prelude::*; struct State { ecs: World, resources: Resources, - systems: Schedule, + input_systems: Schedule, + player_systems: Schedule, + monster_systems: Schedule, } impl State { fn new() -> Self { @@ -45,10 +49,13 @@ impl State { resources.insert(map_builder.map); resources.insert(Camera::new(map_builder.player_start)); + resources.insert(TurnState::AwaitingInput); State { ecs, resources, - systems: build_scheduler(), + input_systems: input_build_scheduler(), + player_systems: player_build_scheduler(), + monster_systems: monster_build_scheduler(), } } } @@ -59,7 +66,19 @@ impl GameState for State { ctx.set_active_console(1); ctx.cls(); self.resources.insert(ctx.key); - self.systems.execute(&mut self.ecs, &mut self.resources); + //self.systems.execute(&mut self.ecs, &mut self.resources); + let current_state = self.resources.get::().unwrap().clone(); + match current_state { + TurnState::AwaitingInput => self + .input_systems + .execute(&mut self.ecs, &mut self.resources), + TurnState::PlayerTurn => self + .player_systems + .execute(&mut self.ecs, &mut self.resources), + TurnState::MonsterTurn => self + .monster_systems + .execute(&mut self.ecs, &mut self.resources), + } render_draw_buffer(ctx).expect("Render error"); } } diff --git a/src/spawners.rs b/src/spawners.rs index 8415a31..52753f6 100644 --- a/src/spawners.rs +++ b/src/spawners.rs @@ -24,5 +24,6 @@ pub fn spawn_monster(ecs: &mut World, rng: &mut RandomNumberGenerator, pos: Poin _ => to_cp437('g'), // goblin }, }, + MovingRandomly {}, )); } diff --git a/src/systems/end_turn.rs b/src/systems/end_turn.rs new file mode 100644 index 0000000..af8615e --- /dev/null +++ b/src/systems/end_turn.rs @@ -0,0 +1,11 @@ +use crate::prelude::*; + +#[system] +pub fn end_turn(#[resource] turn_state: &mut TurnState) { + let new_state = match turn_state { + TurnState::AwaitingInput => return, + TurnState::PlayerTurn => TurnState::MonsterTurn, + TurnState::MonsterTurn => TurnState::AwaitingInput, + }; + *turn_state = new_state; +} diff --git a/src/systems/mod.rs b/src/systems/mod.rs index 90c680a..e34db46 100644 --- a/src/systems/mod.rs +++ b/src/systems/mod.rs @@ -1,14 +1,41 @@ use crate::prelude::*; mod collisions; +mod end_turn; mod entity_render; mod map_render; +mod movement; mod player_input; +mod random_move; -pub fn build_scheduler() -> Schedule { +pub fn input_build_scheduler() -> Schedule { Schedule::builder() .add_system(player_input::player_input_system()) - .add_system(collisions::collisions_system()) + .flush() .add_system(map_render::map_render_system()) .add_system(entity_render::entity_render_system()) .build() } +pub fn player_build_scheduler() -> Schedule { + Schedule::builder() + .add_system(movement::movement_system()) + .flush() + .add_system(collisions::collisions_system()) + .flush() + .add_system(map_render::map_render_system()) + .add_system(entity_render::entity_render_system()) + .add_system(end_turn::end_turn_system()) + .build() +} +pub fn monster_build_scheduler() -> Schedule { + Schedule::builder() + .add_system(random_move::random_move_system()) + .flush() + .add_system(movement::movement_system()) + .flush() + .add_system(collisions::collisions_system()) + .flush() + .add_system(map_render::map_render_system()) + .add_system(entity_render::entity_render_system()) + .add_system(end_turn::end_turn_system()) + .build() +} diff --git a/src/systems/movement.rs b/src/systems/movement.rs new file mode 100644 index 0000000..b4fdaaf --- /dev/null +++ b/src/systems/movement.rs @@ -0,0 +1,25 @@ +pub use crate::prelude::*; + +#[system(for_each)] +#[read_component(Player)] +pub fn movement( + entity: &Entity, + want_move: &WantsToMove, + #[resource] map: &Map, + #[resource] camera: &mut Camera, + ecs: &mut SubWorld, + commands: &mut CommandBuffer, +) { + if map.can_enter_tile(want_move.destination) { + commands.add_component(want_move.entity, want_move.destination); + if ecs + .entry_ref(want_move.entity) + .unwrap() + .get_component::() + .is_ok() + { + camera.on_player_move(want_move.destination); + } + } + commands.remove(*entity); +} diff --git a/src/systems/player_input.rs b/src/systems/player_input.rs index f49f067..74d49ad 100644 --- a/src/systems/player_input.rs +++ b/src/systems/player_input.rs @@ -1,14 +1,15 @@ use crate::prelude::*; #[system] -#[write_component(Point)] +#[read_component(Point)] #[read_component(Player)] pub fn player_input( ecs: &mut SubWorld, - #[resource] map: &Map, + commands: &mut CommandBuffer, #[resource] key: &Option, - #[resource] camera: &mut Camera, + #[resource] turn_state: &mut TurnState, ) { + let mut players = <(Entity, &Point)>::query().filter(component::()); if let Some(key) = key { let delta = match key { VirtualKeyCode::Left => Point::new(-1, 0), @@ -17,15 +18,16 @@ pub fn player_input( VirtualKeyCode::Down => Point::new(0, 1), _ => Point::new(0, 0), }; - if delta.x != 0 || delta.y != 0 { - let mut players = <&mut Point>::query().filter(component::()); - players.iter_mut(ecs).for_each(|pos| { - let destination = *pos + delta; - if map.can_enter_tile(destination) { - *pos = destination; - camera.on_player_move(destination); - } - }); - } + players.iter(ecs).for_each(|(entity, pos)| { + let destination = *pos + delta; + commands.push(( + (), + WantsToMove { + entity: *entity, + destination, + }, + )); + }); + *turn_state = TurnState::PlayerTurn; } } diff --git a/src/systems/random_move.rs b/src/systems/random_move.rs new file mode 100644 index 0000000..0931d85 --- /dev/null +++ b/src/systems/random_move.rs @@ -0,0 +1,24 @@ +pub use crate::prelude::*; + +#[system] +#[read_component(Point)] +#[read_component(MovingRandomly)] +pub fn random_move(ecs: &mut SubWorld, commands: &mut CommandBuffer) { + let mut movers = <(Entity, &Point, &MovingRandomly)>::query(); + movers.iter_mut(ecs).for_each(|(entity, pos, _)| { + let mut rng = RandomNumberGenerator::new(); + let destination = match rng.range(0, 4) { + 0 => Point::new(-1, 0), + 1 => Point::new(1, 0), + 2 => Point::new(0, -1), + _ => Point::new(0, 1), + } + *pos; + commands.push(( + (), + WantsToMove { + entity: *entity, + destination, + }, + )); + }); +} diff --git a/src/turn_state.rs b/src/turn_state.rs new file mode 100644 index 0000000..2f8083f --- /dev/null +++ b/src/turn_state.rs @@ -0,0 +1,6 @@ +#[derive(Copy, Clone, Debug, PartialEq)] +pub enum TurnState { + AwaitingInput, + PlayerTurn, + MonsterTurn, +}