From: Matthew Kousoulas Date: Fri, 18 Oct 2024 18:17:57 +0000 (-0400) Subject: Add Camera Controls and Pausing X-Git-Url: http://gitweb.madkous.net/?a=commitdiff_plain;h=HEAD;p=kytagony.git Add Camera Controls and Pausing --- diff --git a/src/camera.rs b/src/camera.rs new file mode 100644 index 0000000..4451673 --- /dev/null +++ b/src/camera.rs @@ -0,0 +1,100 @@ +use bevy::prelude::*; + +pub struct CameraCfg; + +#[derive(Component)] +pub struct MainCamera; + +//#[derive(Event)] +//pub struct PanCamera(pub Vec2); +//#[derive(Event)] +//pub struct ZoomCamera(pub f32); +//#[derive(Event)] +//pub struct RotateCamera(pub f32); + +#[derive(Event)] +pub enum MoveCamera { + Pan(Vec2), + Zoom(f32), + Rotate(f32), + Center(Vec2), + Reset, +} + +impl Plugin for CameraCfg { + fn build(&self, app: &mut App) { + //app.add_event::(); + //app.add_event::(); + //app.add_event::(); + app.add_event::(); + app.add_systems(Startup, setup); + app.add_systems(Update, ( + move_camera.run_if(on_event::()), + //pan_camera.run_if(on_event::()), + //zoom_camera.run_if(on_event::()), + //rotate_camera.run_if(on_event::()), + )); + } +} + +fn setup( + mut commands: Commands, +) { + commands.spawn((Camera2dBundle::default(), MainCamera)); +} + +fn move_camera( + mut e_read: EventReader, + mut camera: Query<(&mut Transform, &mut OrthographicProjection), With> +) { + let Ok((mut trans, mut proj)) = camera.get_single_mut() else { return; }; + let z = trans.translation.z; + for mov in e_read.read() { + match mov { + MoveCamera::Pan(p) => { + let r = trans.rotation.mul_vec3(Vec3::from((*p * proj.scale, z))); + trans.translation += r; + }, + MoveCamera::Zoom(z) => proj.scale += z * proj.scale, + MoveCamera::Rotate(th) => trans.rotation *= Quat::from_rotation_z(*th), + MoveCamera::Center(p) => trans.translation = Vec3::from((*p, z)), + MoveCamera::Reset => { + trans.translation = Vec3::from((Vec2::ZERO, z)); + trans.rotation = Quat::from_rotation_z(0.0); + proj.scale = 1.0; + }, + } + } +} + +//fn pan_camera( +// mut e_read: EventReader, +// mut camera: Query<&mut Transform, With> +//) { +// let Ok(mut camera) = camera.get_single_mut() else { return; }; +// let z = camera.translation.z; +// for PanCamera(p) in e_read.read() { +// camera.translation += Vec3::from((*p, z)); +// } +//} +// +//fn zoom_camera( +// mut e_read: EventReader, +// mut camera: Query<&mut OrthographicProjection, With> +//) { +// //use bevy::render::camera::ScalingMode; +// let Ok(mut camera) = camera.get_single_mut() else { return; }; +// for ZoomCamera(z) in e_read.read() { +// camera.scale += z; +// } +//} +// +//fn rotate_camera( +// mut e_read: EventReader, +// mut camera: Query<&mut Transform, With> +//) { +// let Ok(mut camera) = camera.get_single_mut() else { return; }; +// for RotateCamera(th) in e_read.read() { +// camera.rotation *= Quat::from_rotation_z(*th); +// } +//} diff --git a/src/control.rs b/src/control.rs new file mode 100644 index 0000000..612e8cd --- /dev/null +++ b/src/control.rs @@ -0,0 +1,82 @@ +use bevy::prelude::*; +use std::f32::consts::PI; + +use crate::camera::*; +use crate::PausedState; + +const PAN_SLOW: f32 = 4.0; +const ZOOM_SLOW: f32 = 1.0 / 128.0; +const ROTATE_SLOW: f32 = PI / 512.0; +const PAN_FAST: f32 = 1.0 / 32.0; +const ZOOM_FAST: f32 = 0.03125; +const ROTATE_FAST: f32 = PI / 128.0; + +pub struct Controls; + +impl Plugin for Controls { + fn build(&self, app: &mut App) { + app.add_systems(Update, ( + handle_pause, + handle_camera_input, + )); + } +} + +fn handle_pause( + keyboard_input: Res>, + curr_state: Res>, + mut next_state: ResMut>, +) { + if keyboard_input.just_released(KeyCode::Space) { + next_state.set(match curr_state.get() { + PausedState::Running => PausedState::Paused, + PausedState::Paused => PausedState::Running, + }); + } +} + +fn handle_camera_input( + keyboard_input: Res>, + mut e_write: EventWriter, + //mut e_pan: EventWriter, + //mut e_zoom: EventWriter, + //mut e_rotate: EventWriter, +) { + let fast = keyboard_input.pressed(KeyCode::ShiftLeft) + || keyboard_input.pressed(KeyCode::ShiftRight); + + let p_rate = if fast { PAN_FAST } else { PAN_SLOW }; + let z_rate = if fast { ZOOM_FAST } else { ZOOM_SLOW }; + let r_rate = if fast { ROTATE_FAST } else { ROTATE_SLOW }; + + if keyboard_input.pressed(KeyCode::KeyW) { + e_write.send(MoveCamera::Pan(Vec2::Y * p_rate)); + } + if keyboard_input.pressed(KeyCode::KeyS) { + e_write.send(MoveCamera::Pan(Vec2::NEG_Y * p_rate)); + } + if keyboard_input.pressed(KeyCode::KeyA) { + e_write.send(MoveCamera::Pan(Vec2::NEG_X * p_rate)); + } + if keyboard_input.pressed(KeyCode::KeyD) { + e_write.send(MoveCamera::Pan(Vec2::X * p_rate)); + } + + if keyboard_input.pressed(KeyCode::KeyR) { + e_write.send(MoveCamera::Zoom(-z_rate)); + } + if keyboard_input.pressed(KeyCode::KeyV) { + e_write.send(MoveCamera::Zoom(z_rate)); + } + + if keyboard_input.pressed(KeyCode::KeyQ) { + e_write.send(MoveCamera::Rotate(r_rate)); + } + if keyboard_input.pressed(KeyCode::KeyE) { + e_write.send(MoveCamera::Rotate(-r_rate)); + } + + if keyboard_input.pressed(KeyCode::Escape) { + e_write.send(MoveCamera::Reset); + } +} diff --git a/src/main.rs b/src/main.rs index 79a76af..7670538 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,9 +4,13 @@ use bevy::{ mod physics; mod particle; +mod camera; +mod control; use crate::physics::*; use crate::particle::*; +use crate::camera::*; +use crate::control::*; //#[derive(Component)] //struct Head; @@ -15,20 +19,28 @@ struct Diagnostics; #[derive(Component)] #[component(storage = "SparseSet")] struct Selected; -#[derive(Component)] -struct MainCamera; #[derive(Event)] struct SelectAt(Vec2); #[derive(Event)] struct Select(Entity); +#[derive(States, Default, Debug, Clone, PartialEq, Eq, Hash)] +enum PausedState { + #[default] + Running, + Paused, +} + fn main() { App::new() + .add_plugins(DefaultPlugins) .add_event::() .add_event::()) )) + .configure_sets(Update, PhysicsSet.run_if(in_state(PausedState::Running))) .run(); } fn setup( mut commands: Commands, ) { - commands.spawn((Camera2dBundle::default(), MainCamera)); commands.spawn(( Diagnostics, TextBundle::from_sections([ diff --git a/src/particle.rs b/src/particle.rs index da37209..1c0e02f 100644 --- a/src/particle.rs +++ b/src/particle.rs @@ -39,11 +39,16 @@ impl Default for ParticleBundle { } } -pub struct Particles; +pub struct Particles { + pub count: i32, +} impl Plugin for Particles { fn build(&self, app: &mut App) { - app.add_systems(Startup, setup); + let count = self.count; + app.add_systems(Startup, + move |commands: Commands, meshes: ResMut>, materials: ResMut>| + setup(commands, meshes, materials, count)); } } @@ -51,6 +56,7 @@ fn setup( mut commands: Commands, mut meshes: ResMut>, mut materials: ResMut>, + count: i32, ) { commands.insert_resource(ColorPalette { default: materials.add(Color::srgb(1.0, 0.8, 0.2)), @@ -59,7 +65,7 @@ fn setup( commands.insert_resource(MeshPalette { standard: meshes.add(Circle { radius: 10.0 }), }); - commands.add(SpawnGroup { count: 128 }); + commands.add(SpawnGroup { count }); } struct SpawnGroup { @@ -69,7 +75,7 @@ struct SpawnGroup { impl Command for SpawnGroup { fn apply(self, world: &mut World) { fn get_vel(u: f32, v: f32) -> Vec2 { Vec2::from_angle(2.0 * PI * u) * v * 5.0 } - fn get_pos(u: f32, v: f32) -> Vec2 { Vec2::from_angle(2.0 * PI * u) * v * 500.0 } + fn get_pos(u: f32, v: f32) -> Vec2 { Vec2::from_angle(2.0 * PI * u) * v.sqrt() * 500.0 } let mut i = 0; while i < self.count { let colors = world.get_resource::().unwrap(); diff --git a/src/physics.rs b/src/physics.rs index 7457339..b24b700 100644 --- a/src/physics.rs +++ b/src/physics.rs @@ -32,6 +32,9 @@ pub struct Statistics { pub momentum: Vec2, } +#[derive(SystemSet, Debug, Clone, PartialEq, Eq, Hash)] +pub struct PhysicsSet; + pub struct Physics; impl Plugin for Physics { @@ -45,7 +48,8 @@ impl Plugin for Physics { apply_velocity, apply_position, update_statistics, - ).chain()); + ).chain() + .in_set(PhysicsSet)); } } @@ -130,9 +134,9 @@ fn apply_velocity( } fn apply_position(mut query: Query<(&mut Transform, &Position)>) { - for (mut transform, p) in &mut query { + for (mut transform, Position(p)) in &mut query { let z = transform.translation.z; - transform.translation = Vec3::from((p.0 * 1.0, z)); + transform.translation = Vec3::from((*p * 1.0, z)); } }