98 lines
2.8 KiB
Rust
98 lines
2.8 KiB
Rust
use super::{ControlState, ControllerSet, Controls};
|
|
use crate::control::controller_common::MovementSpeedFactor;
|
|
use crate::control::controls::ControllerSettings;
|
|
use crate::{GameState, abilities::TriggerStateRes, player::PlayerBodyMesh};
|
|
use bevy::prelude::*;
|
|
use happy_feet::prelude::{Grounding, KinematicVelocity, MoveInput};
|
|
|
|
use super::controller_common::PlayerMovement;
|
|
|
|
pub struct CharacterControllerPlugin;
|
|
|
|
impl Plugin for CharacterControllerPlugin {
|
|
fn build(&self, app: &mut App) {
|
|
app.add_systems(
|
|
PreUpdate,
|
|
(set_movement_flag, rotate_view, apply_controls)
|
|
.chain()
|
|
.in_set(ControllerSet::ApplyControlsRun)
|
|
.run_if(in_state(GameState::Playing)),
|
|
);
|
|
}
|
|
}
|
|
|
|
/// Sets the movement flag, which is an indicator for the rig animation and the braking system.
|
|
fn set_movement_flag(
|
|
mut player_movement: ResMut<PlayerMovement>,
|
|
controls: Res<Controls>,
|
|
trigger: Res<TriggerStateRes>,
|
|
) {
|
|
let mut direction = controls.keyboard_state.move_dir;
|
|
let deadzone = 0.2;
|
|
|
|
if let Some(gamepad) = controls.gamepad_state {
|
|
direction += gamepad.move_dir;
|
|
}
|
|
|
|
if player_movement.any_direction {
|
|
if direction.length_squared() < deadzone {
|
|
player_movement.any_direction = false;
|
|
}
|
|
} else if direction.length_squared() > deadzone {
|
|
player_movement.any_direction = true;
|
|
}
|
|
|
|
if player_movement.shooting != trigger.is_active() {
|
|
player_movement.shooting = trigger.is_active();
|
|
}
|
|
}
|
|
|
|
fn rotate_view(
|
|
controls: Res<ControlState>,
|
|
mut player: Query<&mut Transform, With<PlayerBodyMesh>>,
|
|
) {
|
|
if controls.view_mode {
|
|
return;
|
|
}
|
|
|
|
for mut tr in &mut player {
|
|
tr.rotate_y(controls.look_dir.x * -0.001);
|
|
}
|
|
}
|
|
|
|
fn apply_controls(
|
|
controls: Res<ControlState>,
|
|
mut character: Query<(
|
|
&mut MoveInput,
|
|
&mut Grounding,
|
|
&mut KinematicVelocity,
|
|
&ControllerSettings,
|
|
&MovementSpeedFactor,
|
|
)>,
|
|
rig_transform_q: Option<Single<&GlobalTransform, With<PlayerBodyMesh>>>,
|
|
) {
|
|
let Ok((mut move_input, mut grounding, mut velocity, settings, move_factor)) =
|
|
character.single_mut()
|
|
else {
|
|
return;
|
|
};
|
|
|
|
let mut direction = -controls.move_dir.extend(0.0).xzy();
|
|
|
|
if let Some(ref rig_transform) = rig_transform_q {
|
|
direction = (rig_transform.forward() * direction.z) + (rig_transform.right() * direction.x);
|
|
}
|
|
|
|
let ground_normal = *grounding.normal().unwrap_or(Dir3::Y);
|
|
|
|
let y_projection = direction.project_onto(ground_normal);
|
|
direction -= y_projection;
|
|
direction = direction.normalize_or_zero();
|
|
|
|
move_input.set(direction * move_factor.0);
|
|
|
|
if controls.jump && grounding.is_grounded() {
|
|
happy_feet::movement::jump(settings.jump_force, &mut velocity, &mut grounding, Dir3::Y)
|
|
}
|
|
}
|