update controls and defaults, add sky color
This commit is contained in:
parent
2049fbcc00
commit
d62f828884
2 changed files with 73 additions and 61 deletions
43
src/lib.rs
43
src/lib.rs
|
@ -4,24 +4,24 @@ use bevy_spatial::{kdtree::KDTree3, SpatialAccess};
|
||||||
|
|
||||||
pub type NNTree = KDTree3<Toid>;
|
pub type NNTree = KDTree3<Toid>;
|
||||||
|
|
||||||
// toid
|
// toid stuff
|
||||||
const SPEED: f32 = 5.0;
|
const SPEED: f32 = 5.0;
|
||||||
const SPEED_DIFF_RANGE: f32 = 0.1; // +/- 8%
|
const SPEED_DIFF_RANGE: f32 = 0.1; // +/- 10%
|
||||||
const MAX_DELTA_V: f32 = std::f32::consts::PI * 2.0; // basically 360 degrees/sec
|
const MAX_DELTA_V: f32 = std::f32::consts::PI * 2.0; // basically 360 degrees/sec
|
||||||
|
|
||||||
// how far from origin before really wanting to come back
|
// how far from origin before really wanting to come back
|
||||||
const RADIUS: f32 = 400.0;
|
const RADIUS: f32 = 50.0;
|
||||||
|
|
||||||
// how close to try to stay to your buddies
|
// how close to try to stay to your buddies
|
||||||
const BUDDY_RADIUS: f32 = 50.0;
|
const BUDDY_RADIUS: f32 = 30.0;
|
||||||
|
|
||||||
const MIN_ALTITUDE: f32 = 1.5;
|
const MIN_ALTITUDE: f32 = 3.5;
|
||||||
|
|
||||||
#[derive(Debug, FromArgs, Resource)]
|
#[derive(Debug, FromArgs, Resource)]
|
||||||
/// Toid Watching
|
/// Toid Watching
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
/// how many Toids to spawn
|
/// how many Toids to spawn
|
||||||
#[argh(option, short = 't', default = "100")]
|
#[argh(option, short = 't', default = "5_000")]
|
||||||
pub toids: usize,
|
pub toids: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,9 +49,9 @@ pub fn turkey_time(
|
||||||
let speed = SPEED + (SPEED * speed_diff);
|
let speed = SPEED + (SPEED * speed_diff);
|
||||||
let vel = unit_vec(r) * speed;
|
let vel = unit_vec(r) * speed;
|
||||||
let buddies = r.gen_range(6..=8);
|
let buddies = r.gen_range(6..=8);
|
||||||
let x = r.gen_range(-5.0..=5.0);
|
let x = r.gen_range(-10.0..=10.0);
|
||||||
let z = r.gen_range(-5.0..=5.0);
|
let z = r.gen_range(-10.0..=10.0);
|
||||||
let y = r.gen_range(0.1..=2.5);
|
let y = r.gen_range(0.1..=5.5);
|
||||||
let spatial_bundle = SpatialBundle {
|
let spatial_bundle = SpatialBundle {
|
||||||
transform: Transform::from_xyz(x, MIN_ALTITUDE + y, z),
|
transform: Transform::from_xyz(x, MIN_ALTITUDE + y, z),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
@ -86,16 +86,6 @@ pub fn update_vel(
|
||||||
let pos = xform.translation;
|
let pos = xform.translation;
|
||||||
let original_dir = dir.clone();
|
let original_dir = dir.clone();
|
||||||
|
|
||||||
// nudge toward origin if too far
|
|
||||||
{
|
|
||||||
let dist = pos.length();
|
|
||||||
let toward_origin = -pos.normalize();
|
|
||||||
let rot = Quat::from_rotation_arc(dir, toward_origin);
|
|
||||||
let pct = (dist / RADIUS).min(1.0);
|
|
||||||
let rot = Quat::IDENTITY.slerp(rot, pct);
|
|
||||||
dir = rot.mul_vec3(dir).normalize();
|
|
||||||
}
|
|
||||||
|
|
||||||
// find buddies and orient; point more towards further-away buddies
|
// find buddies and orient; point more towards further-away buddies
|
||||||
for buddy in buddies.0.iter() {
|
for buddy in buddies.0.iter() {
|
||||||
let bp = positions.get(buddy).unwrap_or(&pos);
|
let bp = positions.get(buddy).unwrap_or(&pos);
|
||||||
|
@ -108,20 +98,31 @@ pub fn update_vel(
|
||||||
}
|
}
|
||||||
|
|
||||||
// avoid flying into neighbors
|
// avoid flying into neighbors
|
||||||
|
let min_dist = speed / 2.0;
|
||||||
for neighbor in index
|
for neighbor in index
|
||||||
.within_distance(pos, speed)
|
.within_distance(pos, min_dist)
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|n| n.1.is_some() && n.1.unwrap() != entity)
|
.filter(|n| n.1.is_some() && n.1.unwrap() != entity)
|
||||||
{
|
{
|
||||||
let bp = neighbor.0;
|
let bp = neighbor.0;
|
||||||
let bdir = pos - bp;
|
let bdir = pos - bp;
|
||||||
let dist = bdir.length();
|
let dist = bdir.length();
|
||||||
let s = 1.0 - (dist / speed).min(1.0);
|
let s = 1.0 - (dist / min_dist).min(1.0);
|
||||||
let rot = Quat::from_rotation_arc(dir, bdir.normalize());
|
let rot = Quat::from_rotation_arc(dir, bdir.normalize());
|
||||||
let rot = Quat::IDENTITY.slerp(rot, s);
|
let rot = Quat::IDENTITY.slerp(rot, s);
|
||||||
dir = rot.mul_vec3(dir).normalize();
|
dir = rot.mul_vec3(dir).normalize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// nudge toward origin if too far
|
||||||
|
{
|
||||||
|
let dist = pos.length();
|
||||||
|
let toward_origin = -pos.normalize();
|
||||||
|
let s = (dist / RADIUS).min(1.0);
|
||||||
|
let rot = Quat::from_rotation_arc(dir, toward_origin);
|
||||||
|
let rot = Quat::IDENTITY.slerp(rot, s);
|
||||||
|
dir = rot.mul_vec3(dir).normalize();
|
||||||
|
}
|
||||||
|
|
||||||
// nudge up if too low
|
// nudge up if too low
|
||||||
if pos.y < MIN_ALTITUDE {
|
if pos.y < MIN_ALTITUDE {
|
||||||
let dh = MIN_ALTITUDE - pos.y;
|
let dh = MIN_ALTITUDE - pos.y;
|
||||||
|
|
91
src/main.rs
91
src/main.rs
|
@ -1,21 +1,28 @@
|
||||||
use bevy::prelude::*;
|
use std::time::Duration;
|
||||||
use bevy_spatial::{AutomaticUpdate, TransformMode};
|
|
||||||
|
|
||||||
use audubon::*;
|
use audubon::*;
|
||||||
|
use bevy::prelude::*;
|
||||||
|
use bevy_spatial::{AutomaticUpdate, TransformMode};
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let config: audubon::Config = argh::from_env();
|
let config: audubon::Config = argh::from_env();
|
||||||
App::new()
|
App::new()
|
||||||
.add_plugins(DefaultPlugins)
|
.add_plugins(DefaultPlugins)
|
||||||
.add_plugins(AutomaticUpdate::<Toid>::new().with_transform(TransformMode::GlobalTransform))
|
.add_plugins(
|
||||||
|
AutomaticUpdate::<Toid>::new()
|
||||||
|
.with_transform(TransformMode::GlobalTransform)
|
||||||
|
.with_frequency(Duration::from_millis(150)),
|
||||||
|
)
|
||||||
.insert_resource(config)
|
.insert_resource(config)
|
||||||
.insert_resource(Positions::default())
|
.insert_resource(Positions::default())
|
||||||
|
.insert_resource(ClearColor(Color::rgb(0.64, 0.745, 0.937))) // a nice light blue
|
||||||
|
.insert_resource(AmbientLight {
|
||||||
|
color: Color::WHITE,
|
||||||
|
brightness: 1.0,
|
||||||
|
})
|
||||||
.add_systems(Startup, setup)
|
.add_systems(Startup, setup)
|
||||||
.add_systems(Update, (update_pos, update_buddies, update_vel).chain())
|
.add_systems(Update, (update_pos, update_buddies, update_vel).chain())
|
||||||
.add_systems(
|
.add_systems(Update, (rotate_camera, bevy::window::close_on_esc))
|
||||||
Update,
|
|
||||||
(rotate_camera, update_config, bevy::window::close_on_esc),
|
|
||||||
)
|
|
||||||
.run();
|
.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,12 +36,12 @@ fn setup(
|
||||||
let rand = &mut rand::thread_rng();
|
let rand = &mut rand::thread_rng();
|
||||||
|
|
||||||
commands.spawn(Camera3dBundle {
|
commands.spawn(Camera3dBundle {
|
||||||
transform: Transform::from_xyz(0., 3.5, 40.).looking_at(Vec3::new(0.0, 10.0, 0.0), Vec3::Y),
|
transform: Transform::from_xyz(0., 5.0, 25.).looking_at(Vec3::new(0.0, 5.0, 0.0), Vec3::Y),
|
||||||
..default()
|
..default()
|
||||||
});
|
});
|
||||||
// plane
|
// plane
|
||||||
commands.spawn(PbrBundle {
|
commands.spawn(PbrBundle {
|
||||||
mesh: meshes.add(Mesh::from(shape::Plane::from_size(50.0))),
|
mesh: meshes.add(Mesh::from(shape::Plane::from_size(500.0))),
|
||||||
material: materials.add(Color::rgb(0.3, 0.5, 0.3).into()),
|
material: materials.add(Color::rgb(0.3, 0.5, 0.3).into()),
|
||||||
..default()
|
..default()
|
||||||
});
|
});
|
||||||
|
@ -45,23 +52,10 @@ fn setup(
|
||||||
let _ = turkey_time(&mut commands, &toid_model, rand);
|
let _ = turkey_time(&mut commands, &toid_model, rand);
|
||||||
}
|
}
|
||||||
|
|
||||||
// light
|
// instructions
|
||||||
commands.spawn(PointLightBundle {
|
|
||||||
point_light: PointLight {
|
|
||||||
intensity: 1500.0,
|
|
||||||
shadows_enabled: true,
|
|
||||||
..default()
|
|
||||||
},
|
|
||||||
transform: Transform::from_xyz(4.0, 8.0, 4.0),
|
|
||||||
..default()
|
|
||||||
});
|
|
||||||
|
|
||||||
// example instructions
|
|
||||||
commands.spawn(
|
commands.spawn(
|
||||||
TextBundle::from_section(
|
TextBundle::from_section(
|
||||||
"Press 'D' to toggle drawing gizmos on top of everything else in the scene\n\
|
"Up and down for camera forward and back; hold shift to change height.\nLeft and right to rotate camera; hold shift to translate.\nPress 'r' to look back at the origin. Press 'ESC' to quit.",
|
||||||
Press 'P' to toggle perspective for line gizmos\n\
|
|
||||||
Hold 'Left' or 'Right' to change the line width",
|
|
||||||
TextStyle {
|
TextStyle {
|
||||||
font_size: 20.,
|
font_size: 20.,
|
||||||
..default()
|
..default()
|
||||||
|
@ -76,27 +70,44 @@ fn setup(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn rotate_camera(mut query: Query<&mut Transform, With<Camera>>, time: Res<Time>) {
|
fn rotate_camera(mut query: Query<&mut Transform, With<Camera>>, keys: Res<Input<KeyCode>>) {
|
||||||
let mut transform = query.single_mut();
|
let mut xform = query.single_mut();
|
||||||
|
|
||||||
transform.rotate_around(Vec3::ZERO, Quat::from_rotation_y(time.delta_seconds() / 2.));
|
let forward = xform.forward() * 0.7;
|
||||||
}
|
let right = xform.right();
|
||||||
|
|
||||||
fn update_config(mut config: ResMut<GizmoConfig>, keyboard: Res<Input<KeyCode>>, time: Res<Time>) {
|
if keys.pressed(KeyCode::Right) {
|
||||||
if keyboard.just_pressed(KeyCode::D) {
|
if keys.pressed(KeyCode::ShiftLeft) || keys.pressed(KeyCode::ShiftRight) {
|
||||||
config.depth_bias = if config.depth_bias == 0. { -1. } else { 0. };
|
xform.translation += right;
|
||||||
|
} else {
|
||||||
|
xform.rotate(Quat::from_rotation_y(-0.08));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if keys.pressed(KeyCode::Left) {
|
||||||
|
if keys.pressed(KeyCode::ShiftLeft) || keys.pressed(KeyCode::ShiftRight) {
|
||||||
|
xform.translation -= right;
|
||||||
|
} else {
|
||||||
|
xform.rotate(Quat::from_rotation_y(0.08));
|
||||||
}
|
}
|
||||||
if keyboard.just_pressed(KeyCode::P) {
|
|
||||||
// Toggle line_perspective
|
|
||||||
config.line_perspective ^= true;
|
|
||||||
// Increase the line width when line_perspective is on
|
|
||||||
config.line_width *= if config.line_perspective { 5. } else { 1. / 5. };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if keyboard.pressed(KeyCode::Right) {
|
if keys.pressed(KeyCode::Up) {
|
||||||
config.line_width += 5. * time.delta_seconds();
|
if keys.pressed(KeyCode::ShiftLeft) || keys.pressed(KeyCode::ShiftRight) {
|
||||||
|
xform.translation += Vec3::Y;
|
||||||
|
} else {
|
||||||
|
xform.translation += forward;
|
||||||
}
|
}
|
||||||
if keyboard.pressed(KeyCode::Left) {
|
}
|
||||||
config.line_width -= 5. * time.delta_seconds();
|
if keys.pressed(KeyCode::Down) {
|
||||||
|
if keys.pressed(KeyCode::ShiftLeft) || keys.pressed(KeyCode::ShiftRight) {
|
||||||
|
xform.translation -= Vec3::Y;
|
||||||
|
} else {
|
||||||
|
xform.translation -= forward;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if keys.just_pressed(KeyCode::R) {
|
||||||
|
let height = xform.translation.y;
|
||||||
|
xform.look_at(Vec3::new(0.0, height, 0.0), Vec3::Y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue