bevy-combat-proto/src/player/systems.rs

99 lines
3.2 KiB
Rust

//! Player systems
use bevy_trait_query::One;
use crate::timer::BpmTimer;
use super::*;
/// Do something based on [PlayerInput]
pub fn handle_input(
mut commands: Commands,
time: Res<Time>,
player_query: Query<(
Entity,
&Player,
&InputState,
&mut KinematicCharacterController,
&mut Sprite,
Option<&mut AttackGraph>,
Option<One<&dyn Weapon>>,
Option<&states::Free>,
Option<&states::Choosing>,
Option<&mut states::Attacking>,
Option<&mut states::Awaiting>,
)>,
timer: Res<BpmTimer>,
) {
let bpm = timer.get_bpm();
for (
// Basic things
player_id,
player,
action_state,
mut controller,
mut sprite,
// Weapon
maybe_attack_graph,
maybe_weapon,
// States
maybe_free,
maybe_choosing,
maybe_attacking,
maybe_awaiting,
) in player_query {
if maybe_free.is_some() {
let direction = action_state.clamped_value(&PlayerInput::Move);
controller.translation = Some(vec2(direction * player.speed * time.delta_secs(), 0.));
if direction != 0. {
sprite.flip_x = direction < 0.;
}
} else if let Some(states::Choosing { log }) = maybe_choosing &&
let Some(mut attack_graph) = maybe_attack_graph {
if let Some(next_state) = attack_graph.next(*log) {
let accuracy = timer.accuracy();
let next_attack = match *log {
PlayerInput::LightAttack => {
states::Attacking::new(next_state, accuracy, 1., bpm)
},
PlayerInput::HeavyAttack => {
states::Attacking::new(next_state, accuracy, 2., bpm)
},
_ => unreachable!(),
};
commands.entity(player_id).insert(states::NextAttack(next_attack));
} else {
commands.entity(player_id).insert(Done::Failure);
}
} else if let Some(mut attacking) = maybe_attacking {
attacking.timer.tick(time.delta());
if attacking.timer.just_finished() {
info!("{}", attacking.accuracy);
commands.entity(player_id).insert(Done::Success);
let Some(weapon) = maybe_weapon else {
error!("No weapon provided for player");
return;
};
if let Some(attack_area) = weapon.attack_area(attacking.phys, attacking.accuracy) {
let offset = weapon.attack_offset();
let direction = if sprite.flip_x { vec2(-1., 1.) } else { vec2(1., 1.) };
commands.entity(player_id)
.with_child(attack_area.into_bundle(offset * direction, sprite.flip_x, GROUP_ENEMY));
}
}
} else if let Some(mut awaiting) = maybe_awaiting {
awaiting.timer.tick(time.delta());
if awaiting.timer.just_finished() {
commands.entity(player_id).insert(Done::Success);
}
}
}
}