generated from 2ndbeam/bevy-template
99 lines
3.2 KiB
Rust
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);
|
|
}
|
|
}
|
|
}
|
|
}
|