track cursor

This commit is contained in:
Matthew Deville 2026-09-28 23:17:46 +02:00
parent af4065e149
commit 96c27d4b0d
5 changed files with 53 additions and 4 deletions

View file

@ -3,6 +3,7 @@ use std::f32::consts::PI;
use crate::{ use crate::{
config::ModelConfig, config::ModelConfig,
pointer::PointerTarget,
spatial_grid::{SpatialGrid, update_spatial_grid}, spatial_grid::{SpatialGrid, update_spatial_grid},
}; };
@ -122,6 +123,7 @@ fn update_boids(
window: Single<&Window, With<bevy::window::PrimaryWindow>>, window: Single<&Window, With<bevy::window::PrimaryWindow>>,
time: Res<Time<Fixed>>, time: Res<Time<Fixed>>,
grid: Res<SpatialGrid>, grid: Res<SpatialGrid>,
pointer: Res<PointerTarget>,
mut query: Query<(Entity, &mut Boid, &mut Transform)>, mut query: Query<(Entity, &mut Boid, &mut Transform)>,
) { ) {
let dt = time.delta_secs(); let dt = time.delta_secs();
@ -194,8 +196,18 @@ fn update_boids(
// Push each boid forward along its current heading // Push each boid forward along its current heading
let self_force = boid.velocity.normalize_or_zero() * model_config.self_acceleration; let self_force = boid.velocity.normalize_or_zero() * model_config.self_acceleration;
let acceleration = // Pull towards the mouse cursor or touch point
boundary_force + separation_force + alignment_force + cohesion_force + self_force; let attraction_force = pointer.0.map_or(Vec2::ZERO, |target| {
(target - transform.translation.xy()).normalize_or_zero()
* model_config.attraction_force
});
let acceleration = boundary_force
+ separation_force
+ alignment_force
+ cohesion_force
+ self_force
+ attraction_force;
boid.velocity += acceleration * dt; boid.velocity += acceleration * dt;
boid.velocity = boid.velocity.clamp_length_max(model_config.max_velocity); boid.velocity = boid.velocity.clamp_length_max(model_config.max_velocity);

View file

@ -22,6 +22,7 @@ pub struct ModelConfig {
pub cohesion_factor: f32, pub cohesion_factor: f32,
pub separation_factor: f32, pub separation_factor: f32,
pub self_acceleration: f32, pub self_acceleration: f32,
pub attraction_force: f32,
} }
impl Default for ModelConfig { impl Default for ModelConfig {
@ -36,7 +37,8 @@ impl Default for ModelConfig {
alignment_factor: 0.3, alignment_factor: 0.3,
cohesion_factor: 0.2, cohesion_factor: 0.2,
separation_factor: 500.0, separation_factor: 500.0,
self_acceleration: 30.0, self_acceleration: 100.0,
attraction_force: 100.0,
} }
} }
} }

View file

@ -1,5 +1,6 @@
mod boids; mod boids;
mod config; mod config;
mod pointer;
mod spatial_grid; mod spatial_grid;
mod ui; mod ui;
@ -18,7 +19,12 @@ fn main() {
}), }),
..default() ..default()
})) }))
.add_plugins((config::ConfigPlugin, boids::BoidsPlugin, ui::ConfigUiPlugin)) .add_plugins((
config::ConfigPlugin,
pointer::PointerPlugin,
boids::BoidsPlugin,
ui::ConfigUiPlugin,
))
.add_systems(Startup, |mut commands: Commands| { .add_systems(Startup, |mut commands: Commands| {
commands.spawn(Camera2d); commands.spawn(Camera2d);
}) })

28
src/pointer.rs Normal file
View file

@ -0,0 +1,28 @@
use bevy::{prelude::*, window::PrimaryWindow};
pub struct PointerPlugin;
impl Plugin for PointerPlugin {
fn build(&self, app: &mut App) {
app.init_resource::<PointerTarget>()
.add_systems(Update, update_pointer_target);
}
}
/// World position of the active touch or mouse cursor, if any.
#[derive(Resource, Default)]
pub struct PointerTarget(pub Option<Vec2>);
fn update_pointer_target(
window: Single<&Window, With<PrimaryWindow>>,
camera: Single<(&Camera, &GlobalTransform)>,
touches: Res<Touches>,
mut target: ResMut<PointerTarget>,
) {
let (camera, camera_transform) = *camera;
// Touch and cursor positions are both in logical window pixels
target.0 = touches
.first_pressed_position()
.or_else(|| window.cursor_position())
.and_then(|position| camera.viewport_to_world_2d(camera_transform, position).ok());
}

View file

@ -28,6 +28,7 @@ const CONFIG_FIELDS: &[(&str, f32)] = &[
("cohesion_factor", 0.05), ("cohesion_factor", 0.05),
("separation_factor", 10.0), ("separation_factor", 10.0),
("self_acceleration", 5.0), ("self_acceleration", 5.0),
("attraction_force", 10.0),
]; ];
#[derive(Component)] #[derive(Component)]