use bevy::{prelude::*, utils::HashSet}; use crate::bike::CyberBikeBody; #[derive(Component)] pub struct CyberCameras; #[derive(Debug, Resource)] pub struct DebugCamOffset { pub rot: f32, pub dist: f32, pub alt: f32, } impl Default for DebugCamOffset { fn default() -> Self { DebugCamOffset { rot: 60.0, dist: 30.0, alt: 4.0, } } } fn spawn_camera(mut commands: Commands) { commands.spawn(Camera3d::default()).insert(CyberCameras); } fn update_camera_pos(mut offset: ResMut, mut keys: ResMut>) { let keyset: HashSet<_> = keys.get_pressed().collect(); let shifted = keyset.contains(&KeyCode::ShiftLeft) || keyset.contains(&KeyCode::ShiftRight); for key in keyset { match key { KeyCode::ArrowLeft => offset.rot -= 5.0, KeyCode::ArrowRight => offset.rot += 5.0, KeyCode::ArrowUp => { if shifted { offset.alt += 0.5; } else { offset.dist -= 0.5; } } KeyCode::ArrowDown => { if shifted { offset.alt -= 0.5; } else { offset.dist += 0.5; } } KeyCode::KeyR => { *offset = DebugCamOffset::default(); } _ => continue, } } let released: Vec<_> = keys.get_just_released().copied().collect(); for key in released { keys.clear_just_released(key); } } fn follow_bike( mut camera: Query<&mut Transform, (With, Without)>, bike: Query<&Transform, (With, Without)>, offset: Res, ) { let bike_xform = *bike.single(); let up = Vec3::Y; let mut ncx = Transform::from_translation(bike_xform.translation); ncx.rotate(Quat::from_axis_angle(up, offset.rot.to_radians())); ncx.translation += ncx.forward() * offset.dist; ncx.translation += ncx.up() * offset.alt; ncx.look_at(bike_xform.translation, up); let mut cam_xform = camera.single_mut(); *cam_xform = ncx; } pub struct CamPlug; impl Plugin for CamPlug { fn build(&self, app: &mut App) { app.insert_resource(DebugCamOffset::default()) .add_systems(Startup, spawn_camera) .add_systems(Update, (follow_bike, update_camera_pos)); } }