Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve first person camera in example #15109

Merged
merged 18 commits into from
Sep 10, 2024
Merged
27 changes: 22 additions & 5 deletions examples/camera/first_person_view_model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@
//! | arrow up | Decrease FOV |
//! | arrow down | Increase FOV |

use std::f32::consts::FRAC_PI_2;

use bevy::color::palettes::tailwind;
use bevy::input::mouse::AccumulatedMouseMotion;
use bevy::pbr::NotShadowCaster;
Expand Down Expand Up @@ -219,18 +221,33 @@ fn spawn_text(mut commands: Commands) {
}

fn move_player(
time: Res<Time>,
accumulated_mouse_motion: Res<AccumulatedMouseMotion>,
mut player: Query<&mut Transform, With<Player>>,
) {
let mut transform = player.single_mut();
let delta = accumulated_mouse_motion.delta;
let dt = time.delta_seconds();
// The factors are just arbitrary mouse sensitivity values.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull these out into constants please :)

Copy link
Member Author

@janhohenheim janhohenheim Sep 10, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I disagree. Pulling them into MOUSE_SENSITIVITY_X and MOUSE_SENSITIVITY_Y

  • makes them less nicely grouped than now, and
  • is semantically wrong. PI is a constant, an aspect ratio is a constant. Mouse sensitivity is a value that should be configurable for accessibility.

As a compromise, I could extract them into a component if you want. Or add a component mentioning that this should be configurable.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Component is nice: it makes it easy for the values to be twiddled via inspectors.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

// It's often nicer to have a faster horizontal sensitivity than vertical.
let mouse_sensitivity = Vec2::new(0.12, 0.10);

if delta != Vec2::ZERO {
let yaw = -delta.x * 0.003;
let pitch = -delta.y * 0.002;
// Order of rotations is important, see <https://gamedev.stackexchange.com/a/136175/103059>
transform.rotate_y(yaw);
transform.rotate_local_x(pitch);
let delta_yaw = -delta.x * dt * mouse_sensitivity.x;
let delta_pitch = -delta.y * dt * mouse_sensitivity.y;

let (yaw, pitch, roll) = transform.rotation.to_euler(EulerRot::YXZ);
let yaw = yaw + delta_yaw;

// If the pitch was ±¹⁄₂ π, the camera would look straight up or down
// In that case, which way should the camera face when looking toward the center again?
// Think about it; the camera has no way of knowing what direction was "forward" in that case!
// It the direction picked will for all intents and purposes be arbitrary.
// To not run into this, we clamp the pitch.
const PITCH_LIMIT: f32 = FRAC_PI_2 - 0.01;
let pitch = (pitch + delta_pitch).clamp(-PITCH_LIMIT, PITCH_LIMIT);

transform.rotation = Quat::from_euler(EulerRot::YXZ, yaw, pitch, roll);
}
}

Expand Down