FPS camera done. Camera rotates but player doesn't

This commit is contained in:
Franklin 2023-09-12 11:33:04 -04:00
parent 8ed0ba71fe
commit 146be24a7c
5 changed files with 104 additions and 36 deletions

View File

@ -1,4 +1,4 @@
use bevy::prelude::*;
use bevy::{prelude::*, window::CursorGrabMode};
use bevy_rapier3d::prelude::*;
use crate::logic::core::player::player_movement::{PlayerMovementInput, move_player, PlayerLinearYState};
@ -6,7 +6,7 @@ use crate::logic::core::player::player_movement::{PlayerMovementInput, move_play
use super::markers::player::Player;
/// System that captures input and fires events
pub fn capture_input(keyboard_input: Res<Input<KeyCode>>, query: Query<(&mut Velocity, &mut ExternalImpulse, &mut PlayerLinearYState), With<Player>>, time: Res<Time>) {
pub fn capture_input(keyboard_input: Res<Input<KeyCode>>, query: Query<(&mut Velocity, &mut ExternalImpulse, &mut PlayerLinearYState, &Transform), With<Player>>, time: Res<Time>) {
// Don't allocate on each frame. Instead Check if any of the inputs are being pressed and then allocate.
if keyboard_input.any_pressed([KeyCode::A, KeyCode::S, KeyCode::D, KeyCode::W, KeyCode::C, KeyCode::Space]) {
let player_movement_input = PlayerMovementInput {
@ -22,3 +22,28 @@ pub fn capture_input(keyboard_input: Res<Input<KeyCode>>, query: Query<(&mut Vel
}
}
pub fn capture_cursor(
mut windows: Query<&mut Window>,
btn: Res<Input<MouseButton>>,
key: Res<Input<KeyCode>>,
) {
let mut window = windows.single_mut();
if btn.just_pressed(MouseButton::Left) {
// if you want to use the cursor, but not let it leave the window,
// use `Confined` mode:
// window.cursor.grab_mode = CursorGrabMode::Confined;
// for a game that doesn't use the cursor (like a shooter):
// use `Locked` mode to keep the cursor in one place
window.cursor.grab_mode = CursorGrabMode::Locked;
// also hide the cursor
window.cursor.visible = false;
}
if key.just_pressed(KeyCode::Escape) {
window.cursor.grab_mode = CursorGrabMode::None;
// also hide the cursor
window.cursor.visible = true;
}
}

View File

@ -1,19 +1,67 @@
use bevy::prelude::*;
use bevy::{prelude::*, input::mouse::MouseMotion};
//use bevy_rapier3d::prelude::*;
use crate::comps::core::{markers::player::Player, camera::MainCamera};
use crate::{comps::core::{markers::player::Player, camera::MainCamera}, utils::rad_deg::radians_from_degrees};
/// Mouse sensitivity and movement speed
#[derive(Resource)]
pub struct MouseMovementSettings {
pub sensitivity: f32,
pub speed: f32,
}
impl Default for MouseMovementSettings {
fn default() -> Self {
Self {
sensitivity: 0.0003,
speed: 12.,
}
}
}
/// Synchronizes camera's translation & rotation (only 1 axis) to player.
pub fn sync_camera_to_player(
player: Query<&Transform, (With<Player>, Without<MainCamera>)>,
mut player: Query<&mut Transform, (With<Player>, Without<MainCamera>)>,
mut camera: Query<&mut Transform, (With<MainCamera>, Without<Player>)>,
) {
let Ok(player) = player.get_single() else { return };
let Ok(mut player) = player.get_single_mut() else { return };
let Ok(mut camera_transform) = camera.get_single_mut() else { return };
camera_transform.translation = player.translation;
camera_transform.rotation = player.rotation;
camera_transform.translation.y += 0.5;
camera_transform.rotate_x(radians_from_degrees(-15.0)); // Make camera slightly point downward.
player.rotation = camera_transform.rotation;
//camera_transform.rotate_x(radians_from_degrees(-15.0)); // Make camera slightly point downward.
}
/// Handles looking around if cursor is locked
pub fn follow_cursor_with_camera(
settings: Res<MouseMovementSettings>,
primary_window: Query<&Window>,
mut motions: EventReader<MouseMotion>,
mut player_query: Query<&mut Transform, (With<Player>, Without<MainCamera>)>,
mut camera_query: Query<&mut Transform, (With<MainCamera>, Without<Player>)>,
) {
if let Ok(window) = primary_window.get_single() {
for player_transform in player_query.iter_mut() {
let (mut yaw, mut pitch, _) = player_transform.rotation.to_euler(EulerRot::YXZ);
for motion in motions.iter() {
let window_scale = window.height().min(window.width());
pitch -= (settings.sensitivity * motion.delta.y * window_scale).to_radians();
yaw -= (settings.sensitivity * motion.delta.x * window_scale).to_radians();
}
pitch = pitch.clamp(-1.54, 1.54);
let desired_rotation_quat = Quat::from_axis_angle(Vec3::Y, yaw) * Quat::from_axis_angle(Vec3::X, pitch);
for mut camera_transform in camera_query.iter_mut() {
camera_transform.rotation = desired_rotation_quat;
}
}
} else {
warn!("Primary window not found for `player_look`!");
}
}

View File

@ -56,8 +56,8 @@ pub struct PlayerMovementInput {
}
/// Applies game logic to determine how player should move.
pub fn move_player(player_movement_input: PlayerMovementInput, mut query: Query<(&mut Velocity, &mut ExternalImpulse, &mut PlayerLinearYState), With<Player>>, time: Res<Time>,) {
for (mut player_velocity, mut player_external_force, mut player_linear_y_state) in &mut query {
pub fn move_player(player_movement_input: PlayerMovementInput, mut query: Query<(&mut Velocity, &mut ExternalImpulse, &mut PlayerLinearYState, &Transform), With<Player>>, time: Res<Time>,) {
for (mut player_velocity, mut player_external_force, mut player_linear_y_state, player_transform) in &mut query {
let crouch_multiplier = if player_movement_input.down {
0.25
} else {
@ -68,17 +68,20 @@ pub fn move_player(player_movement_input: PlayerMovementInput, mut query: Query<
} else {
1.0
};
let local_z = player_transform.local_z();
let forward = -Vec3::new(local_z.x, 0.0, local_z.z);
let right = Vec3::new(local_z.z, 0.0, -local_z.x);
if player_movement_input.front {
player_velocity.linvel.z = apply_movement_acceleration(player_velocity.linvel.z, false, time.delta_seconds(), sprint_multiplier);
player_velocity.linvel = apply_movement_acceleration_to_vec(forward, player_velocity.linvel, time.delta_seconds(), sprint_multiplier);
}
if player_movement_input.back {
player_velocity.linvel.z = apply_movement_acceleration(player_velocity.linvel.z, true, time.delta_seconds(), 1.0);
player_velocity.linvel = apply_movement_acceleration_to_vec(-forward, player_velocity.linvel, time.delta_seconds(), 1.0);
}
if player_movement_input.right {
player_velocity.linvel.x = apply_movement_acceleration(player_velocity.linvel.x, true, time.delta_seconds(), 1.0);
player_velocity.linvel = apply_movement_acceleration_to_vec(right, player_velocity.linvel, time.delta_seconds(), 1.0);
}
if player_movement_input.left {
player_velocity.linvel.x = apply_movement_acceleration(player_velocity.linvel.x, false, time.delta_seconds(), 1.0);
player_velocity.linvel = apply_movement_acceleration_to_vec(-right, player_velocity.linvel, time.delta_seconds(), 1.0);
}
if player_movement_input.up && player_linear_y_state.is_grounded(&PLAYER_JUMP_COOLDOWN_MS) {
@ -91,7 +94,7 @@ pub fn move_player(player_movement_input: PlayerMovementInput, mut query: Query<
if positive { player_velocity.linvel.x = MAX_LINEAR_PLAYER_VELOCITY * crouch_multiplier * sprint_multiplier }
else { player_velocity.linvel.x = MAX_LINEAR_PLAYER_VELOCITY * -1.0 * crouch_multiplier }
}
if player_velocity.linvel.z.abs() > MAX_LINEAR_PLAYER_VELOCITY * crouch_multiplier {
if player_velocity.linvel.z.abs() > MAX_LINEAR_PLAYER_VELOCITY * crouch_multiplier * sprint_multiplier{
let positive = player_velocity.linvel.z.is_sign_positive();
if positive { player_velocity.linvel.z = MAX_LINEAR_PLAYER_VELOCITY * crouch_multiplier }
else { player_velocity.linvel.z = MAX_LINEAR_PLAYER_VELOCITY * -1.0 * crouch_multiplier }
@ -99,21 +102,10 @@ pub fn move_player(player_movement_input: PlayerMovementInput, mut query: Query<
}
}
// currentLinearVelocity + Acceleration * deltaTime
fn apply_movement_acceleration(current_linvel: f32, positive: bool, delta_time_secs: f32, multiplier: f32) -> f32 {
if positive {
if current_linvel.is_sign_positive() {
current_linvel + PLAYER_ACCELERATION * delta_time_secs * multiplier
} else {
// Make it so deacceleration is faster
current_linvel + (PLAYER_ACCELERATION * delta_time_secs * 2.0) * multiplier
}
} else {
if current_linvel.is_sign_negative() {
current_linvel - PLAYER_ACCELERATION * delta_time_secs * multiplier
} else {
// Make it so deacceleration is faster
current_linvel - (PLAYER_ACCELERATION * delta_time_secs * 2.0) * multiplier
}
}
fn apply_movement_acceleration_to_vec(direction: Vec3, current_linvel: Vec3, delta_time_secs: f32, multiplier: f32) -> Vec3 {
current_linvel + (
direction * PLAYER_ACCELERATION * delta_time_secs * multiplier
)
}

View File

@ -10,12 +10,12 @@ pub fn spawn_player(mut commands: Commands) {
.insert(RigidBody::Dynamic)
.insert(GravityScale(2.5))
.insert(Collider::capsule_y(2.0, 2.0))
.insert(Restitution::coefficient(0.3))
.insert(Restitution::coefficient(0.0))
.insert(Friction { coefficient: 0.0, ..Default::default() })
.insert(TransformBundle::from(Transform::from_xyz(3.0, 5.0, 2.0)))
.insert(TransformBundle{ local: Transform::from_xyz(3.0, 5.0, 2.0), global: Default::default() })
.insert(Velocity::zero())
.insert(Damping { linear_damping: 1.0, angular_damping: 1.0 })
.insert(LockedAxes::ROTATION_LOCKED_X | LockedAxes::ROTATION_LOCKED_Z | LockedAxes::ROTATION_LOCKED_Y)
.insert(LockedAxes::ROTATION_LOCKED_Z | LockedAxes::ROTATION_LOCKED_X )
.insert(ColliderMassProperties::Density(2.0))
.insert(ExternalImpulse {
impulse: Vec3::ZERO,

View File

@ -1,11 +1,12 @@
use bevy::prelude::*;
use crate::{logic::core::player::{spawn_player::spawn_player, camera_player_sync::sync_camera_to_player, player_vertical_sync::sync_player_y_state}, comps::core::controller::capture_input};
use crate::{logic::core::player::{spawn_player::spawn_player, camera_player_sync::{sync_camera_to_player, MouseMovementSettings, follow_cursor_with_camera}, player_vertical_sync::sync_player_y_state}, comps::core::controller::{capture_input, capture_cursor}};
use super::{ground::spawn_ground, lighting::setup_lighting, obstacles::spawn_obstacles};
pub fn load_scene(application: &mut App) {
application.insert_resource(MouseMovementSettings::default());
// Startup
application.add_systems(Startup, spawn_ground);
application.add_systems(Startup, spawn_obstacles);
@ -15,7 +16,9 @@ pub fn load_scene(application: &mut App) {
// Update
application.add_systems(Update, capture_input);
application.add_systems(Update, sync_camera_to_player);
application.add_systems(Update, capture_cursor);
application.add_systems(Update, sync_player_y_state);
application.add_systems(Update, follow_cursor_with_camera);
application.add_systems(Startup, setup_lighting);
}