Add collision detection, reaction, and gravity.
This commit is contained in:
parent
2885be2003
commit
f53cd2f848
2 changed files with 73 additions and 68 deletions
|
@ -15,17 +15,12 @@ use heron::{
|
||||||
pub const PLANET_RADIUS: f32 = 75.0;
|
pub const PLANET_RADIUS: f32 = 75.0;
|
||||||
|
|
||||||
const PLAYER_DIST: f32 = PLANET_RADIUS + 100.0;
|
const PLAYER_DIST: f32 = PLANET_RADIUS + 100.0;
|
||||||
const CAM_DIST: f32 = 30.0;
|
const CAM_DIST: f32 = 50.0;
|
||||||
|
|
||||||
#[derive(Component, Default)]
|
#[derive(Component, Default)]
|
||||||
struct PlayerState {
|
struct PlayerState {
|
||||||
velocity: Vec3,
|
velocity: Vec3,
|
||||||
}
|
colliding: bool,
|
||||||
|
|
||||||
#[derive(Default)]
|
|
||||||
struct UpState {
|
|
||||||
player_up: Vec3,
|
|
||||||
cam_up: Vec3,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
@ -49,7 +44,7 @@ impl Default for MovementSettings {
|
||||||
Self {
|
Self {
|
||||||
sensitivity: 1.0,
|
sensitivity: 1.0,
|
||||||
accel: 40.,
|
accel: 40.,
|
||||||
drag: 0.05,
|
drag: 0.0005,
|
||||||
gravity: 10.0,
|
gravity: 10.0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -123,28 +118,20 @@ fn setup_dbg_ui(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||||
.insert(UpText);
|
.insert(UpText);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dbg_ui_system(state: Res<UpState>, mut query: Query<&mut Text, With<UpText>>) {
|
fn ui_system(pstate_query: Query<&PlayerState>, mut text_query: Query<&mut Text, With<UpText>>) {
|
||||||
let cos = state.player_up.dot(state.cam_up);
|
let mut text = text_query.single_mut();
|
||||||
|
let pstate = pstate_query.single();
|
||||||
let mut text = query.single_mut();
|
text.sections[0].value = format!("{:.2}", pstate.velocity.length());
|
||||||
text.sections[0].value = format!(
|
|
||||||
"up: {:?}\ncam_up: {:?}\ntheta: {:.2}",
|
|
||||||
state.player_up,
|
|
||||||
state.cam_up,
|
|
||||||
cos.acos().to_degrees()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn player_move(
|
fn player_move(
|
||||||
time: Res<Time>,
|
time: Res<Time>,
|
||||||
_settings: Res<MovementSettings>,
|
mut bike_query: Query<(&mut Transform, &PlayerState), Without<FlyCam>>,
|
||||||
mut up_state: ResMut<UpState>,
|
|
||||||
mut bike_query: Query<(&mut Transform, &mut PlayerState), Without<FlyCam>>,
|
|
||||||
mut cam_query: Query<(&mut Transform, &FlyCam), Without<PlayerState>>,
|
mut cam_query: Query<(&mut Transform, &FlyCam), Without<PlayerState>>,
|
||||||
) {
|
) {
|
||||||
let dt = time.delta_seconds();
|
let dt = time.delta_seconds();
|
||||||
|
|
||||||
let (mut bike_xform, mut player_state) = bike_query.single_mut();
|
let (mut bike_xform, player_state) = bike_query.single_mut();
|
||||||
let up = bike_xform.translation.normalize();
|
let up = bike_xform.translation.normalize();
|
||||||
let cam_up = bike_xform.up();
|
let cam_up = bike_xform.up();
|
||||||
let cos = up.dot(cam_up);
|
let cos = up.dot(cam_up);
|
||||||
|
@ -170,15 +157,9 @@ fn player_move(
|
||||||
}
|
}
|
||||||
|
|
||||||
if player_state.velocity.is_finite() {
|
if player_state.velocity.is_finite() {
|
||||||
//state.velocity += -up * settings.gravity * dt;
|
|
||||||
bike_xform.translation += player_state.velocity * dt;
|
bike_xform.translation += player_state.velocity * dt;
|
||||||
} else {
|
|
||||||
//state.velocity = -up * settings.gravity * dt;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
up_state.cam_up = cam_up;
|
|
||||||
up_state.player_up = up;
|
|
||||||
|
|
||||||
let (mut cam_xform, _) = cam_query.single_mut();
|
let (mut cam_xform, _) = cam_query.single_mut();
|
||||||
cam_xform.translation = bike_xform.translation + (up * CAM_DIST);
|
cam_xform.translation = bike_xform.translation + (up * CAM_DIST);
|
||||||
cam_xform.look_at(bike_xform.translation, Vec3::Y);
|
cam_xform.look_at(bike_xform.translation, Vec3::Y);
|
||||||
|
@ -247,26 +228,49 @@ fn player_look(
|
||||||
|
|
||||||
transform.rotate(rotation);
|
transform.rotate(rotation);
|
||||||
|
|
||||||
//dbg!(&vel);
|
|
||||||
|
|
||||||
pstate.velocity = vel;
|
pstate.velocity = vel;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cursor_grab(
|
fn collision_detection(
|
||||||
keys: Res<Input<KeyCode>>,
|
mut events: EventReader<CollisionEvent>,
|
||||||
mut windows: ResMut<Windows>,
|
mut query: Query<&mut PlayerState>,
|
||||||
mut query: Query<(&FlyCam, &mut Transform)>,
|
|
||||||
) {
|
) {
|
||||||
let window = windows.get_primary_mut().unwrap();
|
let mut pstate = query.single_mut();
|
||||||
if keys.just_pressed(KeyCode::L) {
|
|
||||||
let (_, mut transform) = query.single_mut();
|
for event in events.iter() {
|
||||||
*transform.as_mut() = transform.looking_at(Vec3::ZERO, Vec3::Y);
|
if let CollisionEvent::Started(_, _) = event {
|
||||||
|
pstate.colliding = true;
|
||||||
|
} else {
|
||||||
|
pstate.colliding = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if keys.just_pressed(KeyCode::U) {
|
}
|
||||||
let lock = !window.cursor_locked();
|
|
||||||
window.set_cursor_lock_mode(lock);
|
fn gravity_collision_reaction(
|
||||||
window.set_cursor_visibility(lock);
|
time: Res<Time>,
|
||||||
|
settings: Res<MovementSettings>,
|
||||||
|
mut query: Query<(&mut PlayerState, &Transform)>,
|
||||||
|
) {
|
||||||
|
let dt = time.delta_seconds();
|
||||||
|
let g = settings.gravity;
|
||||||
|
let (mut pstate, xform) = query.single_mut();
|
||||||
|
|
||||||
|
// first gravity
|
||||||
|
let down = -xform.translation.normalize();
|
||||||
|
let dvel = down * g * dt;
|
||||||
|
let mut vel = if pstate.velocity.is_finite() {
|
||||||
|
pstate.velocity + dvel
|
||||||
|
} else {
|
||||||
|
dvel
|
||||||
|
};
|
||||||
|
|
||||||
|
// now see if we're currently colliding
|
||||||
|
if pstate.colliding {
|
||||||
|
let dvel = down * vel.dot(down) * 1.02;
|
||||||
|
vel -= dvel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pstate.velocity = vel;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Contains everything needed to add first-person fly camera behavior to your
|
/// Contains everything needed to add first-person fly camera behavior to your
|
||||||
|
@ -277,12 +281,12 @@ impl Plugin for PlayerPlugin {
|
||||||
app.init_resource::<PlayerState>()
|
app.init_resource::<PlayerState>()
|
||||||
.init_resource::<MovementSettings>()
|
.init_resource::<MovementSettings>()
|
||||||
.init_resource::<InputState>()
|
.init_resource::<InputState>()
|
||||||
.init_resource::<UpState>()
|
|
||||||
.add_startup_system(setup_player)
|
.add_startup_system(setup_player)
|
||||||
.add_startup_system(setup_dbg_ui)
|
.add_startup_system(setup_dbg_ui)
|
||||||
.add_system(dbg_ui_system)
|
.add_system(ui_system)
|
||||||
.add_system(player_move.label("move"))
|
.add_system(player_move.label("move"))
|
||||||
.add_system(player_look.after("move"))
|
.add_system(player_look.after("move"))
|
||||||
.add_system(cursor_grab);
|
.add_system(collision_detection)
|
||||||
|
.add_system(gravity_collision_reaction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
47
src/main.rs
47
src/main.rs
|
@ -1,13 +1,8 @@
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use cyber_rider::flycam::{MovementSettings, PlayerPlugin, PLANET_RADIUS};
|
use cyber_rider::flycam::{MovementSettings, PlayerPlugin, PLANET_RADIUS};
|
||||||
|
use heron::prelude::*;
|
||||||
|
|
||||||
/*
|
const LIGHT_RANGE: f32 = PLANET_RADIUS * 0.6;
|
||||||
stolen with neither shame nor pity from
|
|
||||||
git@github.com:sburris0/bevy_flycam.git, b90f6fc, which is copyright 2020
|
|
||||||
Spencer Burris
|
|
||||||
*/
|
|
||||||
|
|
||||||
const LIGHT_RANGE: f32 = PLANET_RADIUS * 2.2;
|
|
||||||
const LIGHT_DIST: f32 = PLANET_RADIUS * 1.2;
|
const LIGHT_DIST: f32 = PLANET_RADIUS * 1.2;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
@ -15,6 +10,7 @@ fn main() {
|
||||||
.insert_resource(Msaa { samples: 4 })
|
.insert_resource(Msaa { samples: 4 })
|
||||||
.add_plugins(DefaultPlugins)
|
.add_plugins(DefaultPlugins)
|
||||||
.add_plugin(PlayerPlugin)
|
.add_plugin(PlayerPlugin)
|
||||||
|
.add_plugin(PhysicsPlugin::default())
|
||||||
.insert_resource(MovementSettings {
|
.insert_resource(MovementSettings {
|
||||||
sensitivity: 0.3, // default: 1.0
|
sensitivity: 0.3, // default: 1.0
|
||||||
accel: 20.0, // default: 40.0
|
accel: 20.0, // default: 40.0
|
||||||
|
@ -43,21 +39,21 @@ fn setup(
|
||||||
mut materials: ResMut<Assets<StandardMaterial>>,
|
mut materials: ResMut<Assets<StandardMaterial>>,
|
||||||
) {
|
) {
|
||||||
let red_light = PointLight {
|
let red_light = PointLight {
|
||||||
intensity: 5_000.0,
|
intensity: 1_000.0,
|
||||||
range: LIGHT_RANGE,
|
range: LIGHT_RANGE,
|
||||||
color: Color::RED,
|
color: Color::RED,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
let blue_light = PointLight {
|
let blue_light = PointLight {
|
||||||
intensity: 5_000.0,
|
intensity: 1_000.0,
|
||||||
range: LIGHT_RANGE,
|
range: LIGHT_RANGE,
|
||||||
color: Color::BLUE,
|
color: Color::BLUE,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
let purple_light = PointLight {
|
let purple_light = PointLight {
|
||||||
intensity: 5_000.0,
|
intensity: 1_000.0,
|
||||||
range: LIGHT_RANGE,
|
range: LIGHT_RANGE,
|
||||||
color: Color::PURPLE,
|
color: Color::PURPLE,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
@ -69,20 +65,25 @@ fn setup(
|
||||||
});
|
});
|
||||||
|
|
||||||
// world
|
// world
|
||||||
commands.spawn_bundle(PbrBundle {
|
commands
|
||||||
mesh: meshes.add(Mesh::from(shape::Icosphere {
|
.spawn_bundle(PbrBundle {
|
||||||
radius: PLANET_RADIUS,
|
mesh: meshes.add(Mesh::from(shape::Icosphere {
|
||||||
subdivisions: 6,
|
radius: PLANET_RADIUS,
|
||||||
})),
|
subdivisions: 6,
|
||||||
material: materials.add(StandardMaterial {
|
})),
|
||||||
base_color: Color::GRAY,
|
material: materials.add(StandardMaterial {
|
||||||
metallic: 0.7,
|
base_color: Color::GRAY,
|
||||||
perceptual_roughness: 0.5,
|
metallic: 0.7,
|
||||||
..Default::default()
|
perceptual_roughness: 0.5,
|
||||||
}),
|
..Default::default()
|
||||||
|
}),
|
||||||
|
|
||||||
..Default::default()
|
..Default::default()
|
||||||
});
|
})
|
||||||
|
.insert(RigidBody::Static)
|
||||||
|
.insert(CollisionShape::Sphere {
|
||||||
|
radius: PLANET_RADIUS,
|
||||||
|
});
|
||||||
|
|
||||||
// east light
|
// east light
|
||||||
commands
|
commands
|
||||||
|
|
Loading…
Reference in a new issue