Fix camera getting uneven, clamp top/bottom rotation
This commit is contained in:
parent
f2cb9f0cae
commit
e31a473b3e
1 changed files with 36 additions and 21 deletions
|
@ -1,16 +1,17 @@
|
||||||
use bevy::{
|
use bevy::{
|
||||||
input::mouse::MouseMotion,
|
input::mouse::MouseMotion,
|
||||||
prelude::*,
|
prelude::*,
|
||||||
render::camera::{Camera, PerspectiveProjection, VisibleEntities},
|
render::camera::{PerspectiveProjection, VisibleEntities},
|
||||||
};
|
};
|
||||||
use bevy_rapier3d::{
|
use bevy_rapier3d::{
|
||||||
na::Matrix3x1,
|
na::{clamp, wrap, Matrix3x1},
|
||||||
physics::RigidBodyHandleComponent,
|
physics::RigidBodyHandleComponent,
|
||||||
rapier::{
|
rapier::{
|
||||||
dynamics::{RigidBody, RigidBodyBuilder, RigidBodySet},
|
dynamics::{RigidBody, RigidBodyBuilder, RigidBodySet},
|
||||||
geometry::ColliderBuilder,
|
geometry::ColliderBuilder,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
use std::f32::consts::{FRAC_PI_2, PI};
|
||||||
|
|
||||||
pub struct PlayerPlugin;
|
pub struct PlayerPlugin;
|
||||||
|
|
||||||
|
@ -32,6 +33,12 @@ struct State {
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct PlayerMarker;
|
struct PlayerMarker;
|
||||||
|
|
||||||
|
#[derive(Default, Debug)]
|
||||||
|
struct CameraData {
|
||||||
|
yaw: f32,
|
||||||
|
pitch: f32,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Bundle)]
|
#[derive(Bundle)]
|
||||||
pub struct PlayerBundle {
|
pub struct PlayerBundle {
|
||||||
pub perspective_projection: PerspectiveProjection,
|
pub perspective_projection: PerspectiveProjection,
|
||||||
|
@ -60,7 +67,7 @@ impl Default for PlayerBundle {
|
||||||
}
|
}
|
||||||
|
|
||||||
const PLAYER_SPEED: f32 = 320.0;
|
const PLAYER_SPEED: f32 = 320.0;
|
||||||
const MOUSE_SENSITIVITY: f32 = 1.0;
|
const MOUSE_SENSITIVITY: f32 = 0.5;
|
||||||
const PLAYER_HEIGHT: f32 = 1.8;
|
const PLAYER_HEIGHT: f32 = 1.8;
|
||||||
const PLAYER_WIDTH: f32 = 0.25;
|
const PLAYER_WIDTH: f32 = 0.25;
|
||||||
|
|
||||||
|
@ -68,10 +75,12 @@ fn init_player(commands: &mut Commands) {
|
||||||
commands
|
commands
|
||||||
.spawn(PlayerBundle::default())
|
.spawn(PlayerBundle::default())
|
||||||
.with_children(|parent| {
|
.with_children(|parent| {
|
||||||
parent.spawn(Camera3dBundle {
|
parent
|
||||||
transform: Transform::from_translation(Vec3::new(0.0, PLAYER_HEIGHT / 2., 0.0)),
|
.spawn(Camera3dBundle {
|
||||||
..Default::default()
|
transform: Transform::from_translation(Vec3::new(0.0, PLAYER_HEIGHT / 2., 0.0)),
|
||||||
});
|
..Default::default()
|
||||||
|
})
|
||||||
|
.with(CameraData::default());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,19 +88,18 @@ fn player_movement_system(
|
||||||
time: Res<Time>,
|
time: Res<Time>,
|
||||||
mut bodies: ResMut<RigidBodySet>,
|
mut bodies: ResMut<RigidBodySet>,
|
||||||
keyboard_input: Res<Input<KeyCode>>,
|
keyboard_input: Res<Input<KeyCode>>,
|
||||||
// TODO: need to use better queries which filters by parent.player_marker
|
camera_transform_query: Query<&Transform, With<CameraData>>,
|
||||||
camera_transform_query: Query<&Transform, With<Camera>>,
|
|
||||||
mut player_query: Query<&RigidBodyHandleComponent, With<PlayerMarker>>,
|
mut player_query: Query<&RigidBodyHandleComponent, With<PlayerMarker>>,
|
||||||
) {
|
) {
|
||||||
for camera_transform in camera_transform_query.iter() {
|
for camera_transform in camera_transform_query.iter() {
|
||||||
for body_handle in player_query.iter_mut() {
|
for body_handle in player_query.iter_mut() {
|
||||||
let body: &mut RigidBody = bodies.get_mut(body_handle.handle()).unwrap();
|
let body: &mut RigidBody = bodies.get_mut(body_handle.handle()).unwrap();
|
||||||
let axis_straight = movement_axis(&keyboard_input, KeyCode::D, KeyCode::A);
|
let axis_strafe = movement_axis(&keyboard_input, KeyCode::D, KeyCode::A);
|
||||||
let axis_strafe = movement_axis(&keyboard_input, KeyCode::S, KeyCode::W);
|
let axis_straight = movement_axis(&keyboard_input, KeyCode::S, KeyCode::W);
|
||||||
|
|
||||||
let rotation = camera_transform.rotation;
|
let rotation = camera_transform.rotation;
|
||||||
let mut speed_2d: Vec3 =
|
let mut speed_2d: Vec3 =
|
||||||
(strafe_vector(&rotation) * axis_straight) + (forward_vector(&rotation) * axis_strafe);
|
(strafe_vector(&rotation) * axis_strafe) + (forward_vector(&rotation) * axis_straight);
|
||||||
if speed_2d.length() != 0.0 {
|
if speed_2d.length() != 0.0 {
|
||||||
speed_2d = speed_2d.normalize() * PLAYER_SPEED;
|
speed_2d = speed_2d.normalize() * PLAYER_SPEED;
|
||||||
}
|
}
|
||||||
|
@ -132,7 +140,7 @@ fn player_look_system(
|
||||||
time: Res<Time>,
|
time: Res<Time>,
|
||||||
mut state: ResMut<State>,
|
mut state: ResMut<State>,
|
||||||
mouse_motion_events: Res<Events<MouseMotion>>,
|
mouse_motion_events: Res<Events<MouseMotion>>,
|
||||||
mut query: Query<&mut Transform, With<Camera>>,
|
mut query: Query<(&mut Transform, &mut CameraData)>,
|
||||||
) {
|
) {
|
||||||
let mut delta: Vec2 = Vec2::zero();
|
let mut delta: Vec2 = Vec2::zero();
|
||||||
for event in state.mouse_motion_event_reader.iter(&mouse_motion_events) {
|
for event in state.mouse_motion_event_reader.iter(&mouse_motion_events) {
|
||||||
|
@ -142,15 +150,22 @@ fn player_look_system(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: need to keep the camera level
|
for (mut transform, mut data) in query.iter_mut() {
|
||||||
for mut transform in query.iter_mut() {
|
data.yaw -= delta.y * MOUSE_SENSITIVITY * time.delta_seconds();
|
||||||
let yaw = -delta.y * MOUSE_SENSITIVITY * time.delta_seconds();
|
data.pitch -= delta.x * MOUSE_SENSITIVITY * time.delta_seconds();
|
||||||
let pitch = -delta.x * MOUSE_SENSITIVITY * time.delta_seconds();
|
// NOTE: if we just use FRAC_PI_2 here, for some reason it results in a blank screen when
|
||||||
|
// looking up/down
|
||||||
|
let half_pi = FRAC_PI_2 - 0.01;
|
||||||
|
data.yaw = clamp(data.yaw, -half_pi, half_pi);
|
||||||
|
data.pitch = wrap(data.pitch, -PI, PI);
|
||||||
|
|
||||||
let quat_yaw = Quat::from_axis_angle(Vec3::unit_x(), yaw);
|
let quat_yaw = Quat::from_axis_angle(Vec3::unit_x(), data.yaw);
|
||||||
let quat_pitch = Quat::from_axis_angle(Vec3::unit_y(), pitch);
|
let quat_pitch = Quat::from_axis_angle(Vec3::unit_y(), data.pitch);
|
||||||
|
|
||||||
let orientation_change: Quat = (quat_pitch * quat_yaw).normalize();
|
let mut orientation = Quat::identity();
|
||||||
transform.rotate(orientation_change);
|
orientation = orientation * quat_yaw;
|
||||||
|
orientation = quat_pitch * orientation;
|
||||||
|
|
||||||
|
transform.rotation = orientation.normalize();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue