diff --git a/src/camera.rs b/src/camera.rs index 8e5bbca..c857dce 100644 --- a/src/camera.rs +++ b/src/camera.rs @@ -44,6 +44,8 @@ pub struct MapCam { pub target_zoom_level: f32, pub pitch: f32, pub yaw: f32, + pub offset_x: f64, + pub offset_z: f64, } impl Default for MapCam { fn default() -> Self { @@ -53,6 +55,8 @@ impl Default for MapCam { target_zoom_level: 10.0, pitch: PI * 0.3, yaw: 0.0, + offset_x: 0.0, + offset_z: 0.0, } } } @@ -125,6 +129,7 @@ pub fn update_map_camera( mut q_camera: Query<&mut Transform, (With, Without)>, q_playercam: Query<&Transform, (With, Without)>, q_target: Query<&Transform, (With, Without, Without)>, + q_target_changed: Query<(), Changed>, mut mouse_events: EventReader, mut er_mousewheel: EventReader, keyboard_input: Res>, @@ -149,9 +154,37 @@ pub fn update_map_camera( // direction parameter for the Transform.look_at function is ambiguous // at the extreme values and the orientation will flicker back/forth. let epsilon = 0.001; + let min_zoom = target.scale.x * 2.0; + let max_zoom = 17e18; // at this point, camera starts glitching mapcam.pitch = (mapcam.pitch + mouse_delta.y / 180.0 * settings.mouse_sensitivity).clamp(-PI / 2.0 + epsilon, PI / 2.0 - epsilon); mapcam.yaw += mouse_delta.x / 180.0 * settings.mouse_sensitivity; + // Reset movement offset if target changes + if !q_target_changed.is_empty() { + mapcam.offset_x = 0.0; + mapcam.offset_z = 0.0; + } + + // Get keyboard movement + let mut offset_x = 0.0; + let mut offset_z = 0.0; + if keyboard_input.pressed(settings.key_forward) { + offset_x -= 1.0; + } + if keyboard_input.pressed(settings.key_back) { + offset_x += 1.0; + } + if keyboard_input.pressed(settings.key_right) { + offset_z -= 1.0; + } + if keyboard_input.pressed(settings.key_left) { + offset_z += 1.0; + } + + // Update movement offset + mapcam.offset_x += (0.01 * offset_x * mapcam.zoom_level) as f64; + mapcam.offset_z += (0.01 * offset_z * mapcam.zoom_level) as f64; + // Update zoom level if !mapcam.initialized { let factor = if target == player_transform { 7.0 } else { 1.0 }; @@ -169,17 +202,18 @@ pub fn update_map_camera( for wheel_event in er_mousewheel.read() { change_zoom -= wheel_event.y * 3.0; } - mapcam.target_zoom_level = (mapcam.target_zoom_level * 1.1f32.powf(change_zoom)).clamp(target.scale.x, 17e18); + mapcam.target_zoom_level = (mapcam.target_zoom_level * 1.1f32.powf(change_zoom)).clamp(min_zoom, max_zoom); let zoom_speed = 0.05; // should be between 0.0001 (slow) and 1.0 (instant) - mapcam.zoom_level = zoom_speed * mapcam.target_zoom_level + (1.0 - zoom_speed) * mapcam.zoom_level; + mapcam.zoom_level = (zoom_speed * mapcam.target_zoom_level + (1.0 - zoom_speed) * mapcam.zoom_level).clamp(min_zoom, max_zoom); // Update point of view - let pov_rotation = Quat::from_euler(EulerRot::XYZ, 0.0, mapcam.yaw, mapcam.pitch); - let point_of_view = pov_rotation * (mapcam.zoom_level * Vec3::new(1.0, 0.0, 0.0)); + let pov_rotation = DQuat::from_euler(EulerRot::XYZ, 0.0, mapcam.yaw as f64, mapcam.pitch as f64); + let offset = DVec3::new(mapcam.offset_x, 0.0, mapcam.offset_z); + let point_of_view = offset + pov_rotation * (mapcam.zoom_level as f64 * DVec3::new(1.0, 0.0, 0.0)); // Apply updates to camera - camera_transform.translation = target.translation + point_of_view; - camera_transform.look_at(target.translation, Vec3::Y); + camera_transform.translation = target.translation + point_of_view.as_vec3(); + camera_transform.look_at(target.translation + offset.as_vec3(), Vec3::Y); } pub fn update_fov(