--- /dev/null
+particle types:
+ locomotive
+ offensive/defensive
+
+game flow:
+
+display:
+ statistic graphs
+ paused overlay
+
+camera controls:
+ center (selected, origin)
+
#[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),
+ ZoomTo(Option<Vec2>, 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 move_camera(
mut e_read: EventReader<MoveCamera>,
- mut camera: Query<(&mut Transform, &mut OrthographicProjection), With<MainCamera>>
+ mut camera: Query<(&Camera, &GlobalTransform, &mut Transform, &mut OrthographicProjection), With<MainCamera>>
) {
- let Ok((mut trans, mut proj)) = camera.get_single_mut() else { return; };
+ let Ok((camera, gtrans, mut trans, mut proj)) = camera.get_single_mut() else { return; };
let z = trans.translation.z;
for mov in e_read.read() {
match mov {
trans.translation += r;
},
MoveCamera::Zoom(z) => proj.scale += z * proj.scale,
+ MoveCamera::ZoomTo(o, z) => {
+ info!("Raw {:?}", o);
+ let p = match o.and_then(|p| camera.viewport_to_world_2d(gtrans, p)) {
+ Some(p) => p,
+ None => Vec2::ZERO,
+ };
+ info!("Proc {:?}", p);
+ info!("Origin {:?}", proj.viewport_origin);
+ proj.viewport_origin = p;//Vec2::new(p.x / window.width() + 0.5, 0.5 - p.y / window.height());
+ proj.scale += z * proj.scale;
+ proj.viewport_origin = Vec2::ZERO;
+ },
MoveCamera::Rotate(th) => trans.rotation *= Quat::from_rotation_z(*th),
MoveCamera::Center(p) => trans.translation = Vec3::from((*p, z)),
MoveCamera::Reset => {
}
}
}
-
-//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);
-// }
-//}
use crate::PausedState;
const PAN_SLOW: f32 = 4.0;
+const PAN_FAST: f32 = 16.0;
const ZOOM_SLOW: f32 = 1.0 / 128.0;
+const ZOOM_FAST: f32 = 1.0 / 32.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;
+const SCROLL_LINE_FACTOR: f32 = 1.0;
+const SCROLL_PIXEL_FACTOR: f32 = 10.0;
+
pub struct Controls;
impl Plugin for Controls {
app.add_systems(Update, (
handle_pause,
handle_camera_input,
+ handle_camera_scroll,
+ //handle_camera_drag,
));
}
}
}
}
+use bevy::window::PrimaryWindow;
+use bevy::input::mouse::*;
+fn handle_camera_scroll(
+ window: Query<&Window, With<PrimaryWindow>>,
+ mut scroll_events: EventReader<MouseWheel>,
+ mut e_write: EventWriter<MoveCamera>,
+) {
+ let window = window.single();
+
+ for scroll in scroll_events.read() {
+ let factor = match scroll.unit {
+ MouseScrollUnit::Pixel => SCROLL_PIXEL_FACTOR,
+ MouseScrollUnit::Line => SCROLL_LINE_FACTOR,
+ };
+
+ //proj.viewport_origin = Vec2::new(p.x / window.width() + 0.5, 0.5 - p.y / window.height());
+ e_write.send(MoveCamera::ZoomTo(window.cursor_position(), ZOOM_FAST * -scroll.y * factor));
+ }
+}
+
+//fn handle_camera_drag(
+// mouse_button: Res<ButtonInput<MouseButton>>,
+// mut motion_events: EventReader<MouseMotion>,
+// mut e_write: EventWriter<MoveCamera>,
+//) {
+// for motion in motion_events.read() {
+//
+// }
+//}
+
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);
-use bevy::{
- prelude::*,
-};
+use bevy::prelude::*;
mod physics;
mod particle;
fn main() {
App::new()
.add_plugins(DefaultPlugins)
- .add_event::<SelectAt>()
- .add_event::<Select>()
- .init_state::<PausedState>()
.add_plugins(Physics)
+ .configure_sets(Update, PhysicsSet.run_if(in_state(PausedState::Running)))
.add_plugins(Particles { count: 128 })
.add_plugins(CameraCfg)
.add_plugins(Controls)
+ .add_event::<SelectAt>()
+ .add_event::<Select>()
+ .init_state::<PausedState>()
.add_systems(Startup, setup)
.add_systems(Update, (
+ cursor,
handle_click,
- write_diagnostics,
+ //write_diagnostics,
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 cursor(
+ window: Query<&Window, With<bevy::window::PrimaryWindow>>,
+ //mut head: Query<&mut Transform, With<Head>>,
+ mut query: Query<&mut Text, With<Diagnostics>>,
+ //mut camera: Query<(&Camera, &GlobalTransform, &mut Transform, &mut OrthographicProjection), With<MainCamera>>
+ camera: Query<(&Camera, &GlobalTransform), With<MainCamera>>
+) {
+ //let mut head = head.single_mut();
+ let window = window.single();
+ let (c, g) = camera.single();
+
+ if let Some(p) = window.cursor_position() {//.and_then(|p| c.viewport_to_world_2d(g, p)) {
+ //head.translation = Vec3::from((p, 1.0));
+ for mut output in &mut query {
+ output.sections[1].value = format!("\t{:?}\n", window.cursor_position());
+ output.sections[2].value = format!("\t{:?}\n", window.resolution);
+ output.sections[3].value = format!("\t{:?}\n", window.width());
+ output.sections[4].value = format!("\t{:?}\n", window.height());
+ output.sections[5].value = format!("\t{:?}\n", p.x / window.width());
+ output.sections[6].value = format!("\t{:?}\n", p.y / window.height());
+ }
+ }
+ //head.translation = window.cursor_position().unwrap();
+}
+
fn setup(
mut commands: Commands,
) {
query: Query<(Entity, &Position)>,
) {
if let Some(SelectAt(p0)) = e_read.read().last() {
- //info!("Clicking at {:?}", p0);
for (e, Position(p1)) in &query {
- //info!("Attempting at {:?}", p1);
if p0.distance(*p1) < 20.0 { // TODO get actual radius
- //info!("Selected at {:?}", p1);
e_write.send(Select(e));
}
}
if let Some(_) = s {
commands.entity(e).remove::<Selected>();
*c = palette.default.clone();
- //info!("Deselecting {:?}", e);
}
}
if let Ok((_, _, mut c)) = query.get_mut(*e) {
commands.entity(*e).insert(Selected);
*c = palette.selected.clone();
- //info!("Selecting {:?}", e);
}
}
}
// }
//}
-
use crate::physics::*;
+#[derive(Component)]
+pub struct Head;
+
#[derive(Resource)]
pub struct ColorPalette {
pub default: Handle<ColorMaterial>,
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.sqrt() * 500.0 }
let mut i = 0;
+
while i < self.count {
let colors = world.get_resource::<ColorPalette>().unwrap();
let meshes = world.get_resource::<MeshPalette>().unwrap();
-
world.spawn((
MaterialMesh2dBundle {
mesh: Mesh2dHandle(meshes.standard.clone()),