]> MadKous Network Git Server - kytagony.git/commitdiff
Add Camera Controls and Pausing master
authorMatthew Kousoulas <shaman.kous@gmail.com>
Fri, 18 Oct 2024 18:17:57 +0000 (14:17 -0400)
committerMatthew Kousoulas <shaman.kous@gmail.com>
Fri, 18 Oct 2024 18:17:57 +0000 (14:17 -0400)
src/camera.rs [new file with mode: 0644]
src/control.rs [new file with mode: 0644]
src/main.rs
src/particle.rs
src/physics.rs

diff --git a/src/camera.rs b/src/camera.rs
new file mode 100644 (file)
index 0000000..4451673
--- /dev/null
@@ -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::<PanCamera>();
+               //app.add_event::<ZoomCamera>();
+               //app.add_event::<RotateCamera>();
+               app.add_event::<MoveCamera>();
+               app.add_systems(Startup, setup);
+               app.add_systems(Update, (
+                               move_camera.run_if(on_event::<MoveCamera>()),
+                               //pan_camera.run_if(on_event::<PanCamera>()),
+                               //zoom_camera.run_if(on_event::<ZoomCamera>()),
+                               //rotate_camera.run_if(on_event::<RotateCamera>()),
+               ));
+       }
+}
+
+fn setup(
+       mut commands: Commands,
+) {
+       commands.spawn((Camera2dBundle::default(), MainCamera));
+}
+
+fn move_camera(
+       mut e_read: EventReader<MoveCamera>,
+       mut camera: Query<(&mut Transform, &mut OrthographicProjection), With<MainCamera>>
+) {
+       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<PanCamera>,
+//     mut camera: Query<&mut Transform, With<MainCamera>>
+//) {
+//     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<ZoomCamera>,
+//     mut camera: Query<&mut OrthographicProjection, With<MainCamera>>
+//) {
+//     //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<RotateCamera>,
+//     mut camera: Query<&mut Transform, With<MainCamera>>
+//) {
+//     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 (file)
index 0000000..612e8cd
--- /dev/null
@@ -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<ButtonInput<KeyCode>>,
+       curr_state: Res<State<PausedState>>,
+       mut next_state: ResMut<NextState<PausedState>>,
+) {
+       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<ButtonInput<KeyCode>>,
+       mut e_write: EventWriter<MoveCamera>,
+       //mut e_pan: EventWriter<PanCamera>,
+       //mut e_zoom: EventWriter<ZoomCamera>,
+       //mut e_rotate: EventWriter<RotateCamera>,
+) {
+       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);
+       }
+}
index 79a76af393ec6f804351273fbd66663d1d9b79e7..7670538b0fa82eb1637eb015db2f2681dffc5aed 100644 (file)
@@ -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::<SelectAt>()
                .add_event::<Select>()
-               .add_plugins(DefaultPlugins)
+               .init_state::<PausedState>()
                .add_plugins(Physics)
-               .add_plugins(Particles)
+               .add_plugins(Particles { count: 128 })
+               .add_plugins(CameraCfg)
+               .add_plugins(Controls)
                .add_systems(Startup, setup)
                .add_systems(Update, (
                                handle_click,
@@ -36,13 +48,13 @@ fn main() {
                                find_select_particle.run_if(on_event::<SelectAt>()),
                                process_select_particle.run_if(on_event::<Select>())
                                ))
+               .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([
index da37209571333d5d435705c1faf8f5a3a7a4d830..1c0e02f077ae97d8490b6fa993d32f4d0a2d700a 100644 (file)
@@ -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<Assets<Mesh>>, materials: ResMut<Assets<ColorMaterial>>|
+                       setup(commands, meshes, materials, count));
        }
 }
 
@@ -51,6 +56,7 @@ fn setup(
        mut commands: Commands,
        mut meshes: ResMut<Assets<Mesh>>,
        mut materials: ResMut<Assets<ColorMaterial>>,
+       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::<ColorPalette>().unwrap();
index 7457339383761dfb99ddf5fe23d97f54cfa8949d..b24b7007183e0475d26ee8bcf6d8f2cc799ea9ea 100644 (file)
@@ -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));
        }
 }