track cursor
This commit is contained in:
parent
af4065e149
commit
96c27d4b0d
5 changed files with 53 additions and 4 deletions
16
src/boids.rs
16
src/boids.rs
|
|
@ -3,6 +3,7 @@ use std::f32::consts::PI;
|
|||
|
||||
use crate::{
|
||||
config::ModelConfig,
|
||||
pointer::PointerTarget,
|
||||
spatial_grid::{SpatialGrid, update_spatial_grid},
|
||||
};
|
||||
|
||||
|
|
@ -122,6 +123,7 @@ fn update_boids(
|
|||
window: Single<&Window, With<bevy::window::PrimaryWindow>>,
|
||||
time: Res<Time<Fixed>>,
|
||||
grid: Res<SpatialGrid>,
|
||||
pointer: Res<PointerTarget>,
|
||||
mut query: Query<(Entity, &mut Boid, &mut Transform)>,
|
||||
) {
|
||||
let dt = time.delta_secs();
|
||||
|
|
@ -194,8 +196,18 @@ fn update_boids(
|
|||
// Push each boid forward along its current heading
|
||||
let self_force = boid.velocity.normalize_or_zero() * model_config.self_acceleration;
|
||||
|
||||
let acceleration =
|
||||
boundary_force + separation_force + alignment_force + cohesion_force + self_force;
|
||||
// Pull towards the mouse cursor or touch point
|
||||
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 = boid.velocity.clamp_length_max(model_config.max_velocity);
|
||||
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ pub struct ModelConfig {
|
|||
pub cohesion_factor: f32,
|
||||
pub separation_factor: f32,
|
||||
pub self_acceleration: f32,
|
||||
pub attraction_force: f32,
|
||||
}
|
||||
|
||||
impl Default for ModelConfig {
|
||||
|
|
@ -36,7 +37,8 @@ impl Default for ModelConfig {
|
|||
alignment_factor: 0.3,
|
||||
cohesion_factor: 0.2,
|
||||
separation_factor: 500.0,
|
||||
self_acceleration: 30.0,
|
||||
self_acceleration: 100.0,
|
||||
attraction_force: 100.0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
mod boids;
|
||||
mod config;
|
||||
mod pointer;
|
||||
mod spatial_grid;
|
||||
mod ui;
|
||||
|
||||
|
|
@ -18,7 +19,12 @@ fn main() {
|
|||
}),
|
||||
..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| {
|
||||
commands.spawn(Camera2d);
|
||||
})
|
||||
|
|
|
|||
28
src/pointer.rs
Normal file
28
src/pointer.rs
Normal 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());
|
||||
}
|
||||
|
|
@ -28,6 +28,7 @@ const CONFIG_FIELDS: &[(&str, f32)] = &[
|
|||
("cohesion_factor", 0.05),
|
||||
("separation_factor", 10.0),
|
||||
("self_acceleration", 5.0),
|
||||
("attraction_force", 10.0),
|
||||
];
|
||||
|
||||
#[derive(Component)]
|
||||
|
|
|
|||
Loading…
Reference in a new issue