diff --git a/README.md b/README.md index 674c642..2bd5168 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,7 @@ Links: - Tab: Toggle HUD/AR - F11: Toggle fullscreen - F: Toggle 3rd person view + - \`: Toggle map - Y: Toggle rotation stabilizer - T: Toggle music - M: Toggle sound effects diff --git a/src/camera.rs b/src/camera.rs index 606ecc3..036fea1 100644 --- a/src/camera.rs +++ b/src/camera.rs @@ -21,10 +21,30 @@ impl Plugin for CameraPlugin { .after(PhysicsSet::Sync) .after(apply_input_to_player) .before(TransformSystem::TransformPropagate)); + app.add_systems(Update, update_map_camera); app.add_systems(Update, update_fov); app.add_systems(PostUpdate, apply_input_to_player .after(PhysicsSet::Sync) .before(TransformSystem::TransformPropagate)); + app.insert_resource(MapCam::default()); + } +} + +#[derive(Resource)] +pub struct MapCam { + zoom_level: f32, + target_zoom_level: f32, + pitch: f32, + yaw: f32, +} +impl Default for MapCam { + fn default() -> Self { + Self { + zoom_level: 1000.0, + target_zoom_level: 10000.0, + pitch: 0.0, + yaw: 0.0, + } } } @@ -72,7 +92,7 @@ pub fn sync_camera_to_player( mut q_camera: Query<&mut Transform, (With, Without)>, q_playercam: Query<(&actor::Actor, &Transform), (With, Without)>, ) { - if q_camera.is_empty() || q_playercam.is_empty() { + if settings.map_active || q_camera.is_empty() || q_playercam.is_empty() { return; } let mut camera_transform = q_camera.get_single_mut().unwrap(); @@ -90,6 +110,50 @@ pub fn sync_camera_to_player( } } +pub fn update_map_camera( + settings: Res, + mut mapcam: ResMut, + mut q_camera: Query<&mut Transform, (With, Without)>, + q_playercam: Query<&Transform, (With, Without)>, + mut mouse_events: EventReader, + keyboard_input: Res>, +) { + if !settings.map_active || q_camera.is_empty() || q_playercam.is_empty() { + return; + } + let mut camera_transform = q_camera.get_single_mut().unwrap(); + let player_transform = q_playercam.get_single().unwrap(); + + // Get mouse movement + let mut mouse_delta = Vec2::ZERO; + for mouse_event in mouse_events.read() { + mouse_delta += mouse_event.delta; + } + // NOTE: we need to subtract a bit from PI/2, otherwise the "up" + // direction parameter for the Transform.look_at function is ambiguous + // at the extreme values and the orientation will flicker back/forth. + let epsilon = 0.000001; + 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; + + // Update zoom level + if keyboard_input.pressed(settings.key_map_zoom_out) { + mapcam.target_zoom_level *= 1.1; + } + if keyboard_input.pressed(settings.key_map_zoom_in) { + mapcam.target_zoom_level /= 1.1; + } + mapcam.zoom_level = 0.1 * mapcam.target_zoom_level + 0.9 * mapcam.zoom_level; + + // 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)); + + // Apply updates to camera + camera_transform.translation = player_transform.translation + point_of_view; + camera_transform.look_at(player_transform.translation, Vec3::Y); +} + pub fn update_fov( q_player: Query<&actor::ExperiencesGForce, With>, mouse_input: Res>, @@ -117,11 +181,16 @@ pub fn update_fov( pub fn handle_input( keyboard_input: Res>, mut settings: ResMut, + mut mapcam: ResMut, mut ew_sfx: EventWriter, ) { if keyboard_input.just_pressed(settings.key_camera) { settings.third_person ^= true; } + if keyboard_input.just_pressed(settings.key_map) { + settings.map_active ^= true; + *mapcam = MapCam::default(); + } if keyboard_input.just_pressed(settings.key_rotation_stabilizer) { ew_sfx.send(audio::PlaySfxEvent(audio::Sfx::Click)); settings.rotation_stabilizer_active ^= true; @@ -136,7 +205,7 @@ fn manage_player_actor( q_ride: Query<(&Transform, &Position, &Rotation, &LinearVelocity, &AngularVelocity), (With, Without)>, ) { for mut vis in &mut q_playercam { - if settings.third_person { + if settings.third_person || settings.map_active { *vis = Visibility::Inherited; } else { @@ -187,6 +256,9 @@ pub fn apply_input_to_player( Option<&actor::PlayerDrivesThis>, ), (With, Without)>, ) { + if settings.map_active { + return; + } let dt = time.delta_seconds(); let mut play_thruster_sound = false; let mut axis_input: DVec3 = DVec3::ZERO; diff --git a/src/var.rs b/src/var.rs index 6c7534b..5e2b6b0 100644 --- a/src/var.rs +++ b/src/var.rs @@ -41,11 +41,17 @@ pub struct Settings { pub hud_color_choices: Color, pub chat_speed: f32, pub hud_active: bool, + pub map_active: bool, pub is_zooming: bool, pub third_person: bool, pub rotation_stabilizer_active: bool, pub key_selectobject: MouseButton, pub key_zoom: MouseButton, + pub key_map: KeyCode, + pub key_map_zoom_out: KeyCode, + pub key_map_zoom_in: KeyCode, + //pub key_map_zoom_out_wheel: MouseButton, + //pub key_map_zoom_in_wheel: MouseButton, pub key_togglehud: KeyCode, pub key_exit: KeyCode, pub key_restart: KeyCode, @@ -143,11 +149,17 @@ impl Default for Settings { hud_color_choices: Color::rgb(0.45, 0.45, 0.45), chat_speed: DEFAULT_CHAT_SPEED * if dev_mode { 2.5 } else { 1.0 }, hud_active: false, + map_active: false, is_zooming: false, third_person: false, rotation_stabilizer_active: true, key_selectobject: MouseButton::Left, key_zoom: MouseButton::Right, + key_map: KeyCode::Backquote, + key_map_zoom_out: KeyCode::ShiftLeft, + key_map_zoom_in: KeyCode::ControlLeft, + //key_map_zoom_out_wheel: KeyCode::Shift, + //key_map_zoom_in_wheel: KeyCode::Shift, key_togglehud: KeyCode::Tab, key_exit: KeyCode::Escape, key_restart: KeyCode::F7,