Add noclip controls

main
copygirl 1 week ago
parent a78d113952
commit 92b5fca3bb
  1. 76
      src/free_camera.rs
  2. 3
      src/main.rs

@ -60,12 +60,82 @@ pub fn camera_free_look(
}
// Update the current camera state's internal yaw and pitch.
let delta = accumulated_mouse_motion.delta * camera.sensitivity;
let motion = accumulated_mouse_motion.delta * camera.sensitivity;
let (min, max) = camera.pitch_limit.clone().into_inner();
camera.yaw = (camera.yaw - delta.x).rem_euclid(TAU); // keep within 0°..360°
camera.pitch = (camera.pitch - delta.y).clamp(min, max);
camera.yaw = (camera.yaw - motion.x).rem_euclid(TAU); // keep within 0°..360°
camera.pitch = (camera.pitch - motion.y).clamp(min, max);
// Override the camera transform's rotation.
transform.rotation = Quat::from_euler(EulerRot::ZYX, 0.0, camera.yaw, camera.pitch);
}
}
// TODO: Make it possible to attach this to any entity, such as the player,
// with the camera being a child. This will require the noclip system
// to know which entity is the camera.
#[derive(Component, Debug)]
pub struct CameraNoClip {
/// The speed at which the camera moves.
pub speed: f32,
/// [`KeyCode`] for forward (relative to camera) translation.
pub key_forward: KeyCode,
/// [`KeyCode`] for backward (relative to camera) translation.
pub key_back: KeyCode,
/// [`KeyCode`] for right (relative to camera) translation.
pub key_right: KeyCode,
/// [`KeyCode`] for left (relative to camera) translation.
pub key_left: KeyCode,
/// [`KeyCode`] for up (global +Y) translation.
pub key_up: KeyCode,
/// [`KeyCode`] for down (global -Y) translation.
pub key_down: KeyCode,
}
impl Default for CameraNoClip {
fn default() -> Self {
Self {
speed: 5.0,
key_forward: KeyCode::KeyW,
key_back: KeyCode::KeyS,
key_right: KeyCode::KeyD,
key_left: KeyCode::KeyA,
key_up: KeyCode::Space,
key_down: KeyCode::ShiftLeft,
}
}
}
pub fn noclip_controller(
time: Res<Time<Real>>,
cursor: Single<&mut CursorOptions>,
key_input: Res<ButtonInput<KeyCode>>,
camera: Single<(&mut Transform, &mut CameraNoClip)>,
) {
let (mut transform, noclip) = camera.into_inner();
if cursor.grab_mode != CursorGrabMode::Locked {
return;
}
#[rustfmt::skip]
let movement = {
let mut movement = Vec3::ZERO;
if key_input.pressed(noclip.key_forward) { movement.z += 1.0; }
if key_input.pressed(noclip.key_back ) { movement.z -= 1.0; }
if key_input.pressed(noclip.key_right ) { movement.x += 1.0; }
if key_input.pressed(noclip.key_left ) { movement.x -= 1.0; }
if key_input.pressed(noclip.key_up ) { movement.y += 1.0; }
if key_input.pressed(noclip.key_down ) { movement.y -= 1.0; }
movement.clamp_length_max(1.0) * noclip.speed
};
if movement != Vec3::ZERO {
let dt = time.delta_secs();
let forward = transform.forward();
let right = transform.right();
transform.translation += movement.x * dt * right;
transform.translation += movement.y * dt * Vec3::Y;
transform.translation += movement.z * dt * forward;
}
}

@ -7,7 +7,7 @@ fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_systems(Startup, setup)
.add_systems(Update, camera_free_look)
.add_systems(Update, (camera_free_look, noclip_controller).chain())
.run();
}
@ -41,5 +41,6 @@ fn setup(
Camera3d::default(),
Transform::from_xyz(-2.5, 4.5, 9.0).looking_at(Vec3::ZERO, Vec3::Y),
CameraFreeLook::default(),
CameraNoClip::default(),
));
}

Loading…
Cancel
Save