diff --git a/game_core/src/control/ai.rs b/game_core/src/control/ai.rs new file mode 100644 index 0000000000000000000000000000000000000000..ba6e5cb2cc6683b070117c2f7487eb7540803122 --- /dev/null +++ b/game_core/src/control/ai.rs @@ -0,0 +1,13 @@ +use bevy::prelude::*; + +#[derive(Copy, Clone, Debug, Component)] +pub struct VisionRange(usize); +#[derive(Copy, Clone, Debug, Component)] +pub struct AggroTarget(Entity); +#[derive(Copy, Clone, Debug, Component)] +pub struct MoveTarget(UVec2); +#[derive(Copy, Clone, Debug, Component)] +pub struct Meander; + +#[derive(Copy, Clone, Debug, Component)] +pub struct ShouldAct; diff --git a/game_core/src/control/mod.rs b/game_core/src/control/mod.rs index 632784b683760f1c0d88f21d0a25a4b2dd03ccfc..09bbf084840d0489b2c1dc08e21cb0e1effdc8f7 100644 --- a/game_core/src/control/mod.rs +++ b/game_core/src/control/mod.rs @@ -1,4 +1,5 @@ pub mod actions; +pub mod ai; pub mod player; mod __plugin { diff --git a/game_core/src/control/player.rs b/game_core/src/control/player.rs index 44f52965a1ae898105d399cd39a807cde946fc09..9d554930f6a50867ec29236088a26ce05b7d6639 100644 --- a/game_core/src/control/player.rs +++ b/game_core/src/control/player.rs @@ -1,31 +1,40 @@ +use std::time::Duration; + use bevy::math::ivec2; use bevy::prelude::*; use crate::entities::lifecycle::Player; +use crate::entities::timing::ActionCooldown; use crate::world::level_map::GridPosition; pub fn handle_player_input( + mut commands: Commands, input: Res<Input<KeyCode>>, - mut query: Query<&mut GridPosition, With<Player>>, + mut query: Query<(Entity, &mut GridPosition), (With<Player>, Without<ActionCooldown>)>, ) { let mut dx = 0; let mut dy = 0; - if input.just_released(KeyCode::D) || input.just_released(KeyCode::Right) { + if input.pressed(KeyCode::D) || input.pressed(KeyCode::Right) { dx += 1; } - if input.just_released(KeyCode::W) || input.just_released(KeyCode::Up) { + if input.pressed(KeyCode::W) || input.pressed(KeyCode::Up) { dy += 1; } - if input.just_released(KeyCode::A) || input.just_released(KeyCode::Left) { + if input.pressed(KeyCode::A) || input.pressed(KeyCode::Left) { dx -= 1; } - if input.just_released(KeyCode::S) || input.just_released(KeyCode::Down) { + if input.pressed(KeyCode::S) || input.pressed(KeyCode::Down) { dy -= 1; } - for mut position in &mut query { - let next_position = (position.0.as_ivec2()) + ivec2(dx, dy); - **position = next_position.as_uvec2(); + for (entity, mut position) in &mut query { + if dx != 0 || dy != 0 { + let next_position = (position.0.as_ivec2()) + ivec2(dx, dy); + **position = next_position.as_uvec2(); + commands + .entity(entity) + .insert(ActionCooldown::from(Duration::from_millis(250))); + } } } diff --git a/game_core/src/entities/timing.rs b/game_core/src/entities/timing.rs index e6c35869ce39ec564a6877eb11b658c58da1982f..e210d3c72e7416bf8a0598030d3aaae4f140bd56 100644 --- a/game_core/src/entities/timing.rs +++ b/game_core/src/entities/timing.rs @@ -1,3 +1,4 @@ +use std::ops::{Deref, DerefMut}; use std::time::Duration; use bevy::prelude::*; @@ -78,6 +79,41 @@ pub fn remove_global_timer_ui(mut commands: Commands, query: Query<Entity, With< } } +#[derive(Copy, Clone, Debug, Component)] +#[repr(transparent)] +#[component(storage = "SparseSet")] +pub struct ActionCooldown(Duration); +impl From<Duration> for ActionCooldown { + fn from(other: Duration) -> Self { + ActionCooldown(other) + } +} +impl Deref for ActionCooldown { + type Target = Duration; + fn deref(&self) -> &Self::Target { + &self.0 + } +} +impl DerefMut for ActionCooldown { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + +pub fn tick_cooldown( + time: Res<Time>, + mut commands: Commands, + mut query: Query<(Entity, &mut ActionCooldown)>, +) { + let delta = time.delta(); + for (entity, mut cooldown) in &mut query { + **cooldown = cooldown.saturating_sub(delta); + if cooldown.is_zero() { + commands.entity(entity).remove::<ActionCooldown>(); + } + } +} + pub struct TimingPlugin; impl Plugin for TimingPlugin { fn build(&self, app: &mut App) { @@ -88,6 +124,7 @@ impl Plugin for TimingPlugin { ConditionSet::new() .run_in_state(AppState::InGame) .with_system(update_global_timer_ui) + .with_system(tick_cooldown) .into(), ) .add_exit_system(AppState::InGame, remove_global_timer_ui);