gamepad controls the camera

This commit is contained in:
Joe Ardent 2021-12-24 18:07:09 -08:00
parent 3f322ba0ea
commit 75870d0161
3 changed files with 185 additions and 122 deletions

134
Cargo.lock generated
View file

@ -101,9 +101,9 @@ dependencies = [
[[package]]
name = "anyhow"
version = "1.0.51"
version = "1.0.52"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b26702f315f53b6071259e15dd9d64528213b44d61de1ec926eca7715d62203"
checksum = "84450d0b4a8bd1ba4144ce8ce718fbc5d071358b1e5384bace6536b3d1f2d5b3"
[[package]]
name = "approx"
@ -185,6 +185,16 @@ dependencies = [
"bevy_internal",
]
[[package]]
name = "bevy-crevice-derive"
version = "0.5.0"
dependencies = [
"bevy_macro_utils",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "bevy_app"
version = "0.5.0"
@ -262,6 +272,16 @@ dependencies = [
"bevy_render",
]
[[package]]
name = "bevy_crevice"
version = "0.5.0"
dependencies = [
"bevy-crevice-derive",
"bytemuck",
"glam",
"mint",
]
[[package]]
name = "bevy_derive"
version = "0.5.0"
@ -341,7 +361,6 @@ dependencies = [
"gltf",
"percent-encoding",
"thiserror",
"wgpu",
]
[[package]]
@ -433,7 +452,6 @@ dependencies = [
"bevy_window",
"bitflags",
"bytemuck",
"crevice",
"wgpu",
]
@ -471,6 +489,7 @@ dependencies = [
"bevy_app",
"bevy_asset",
"bevy_core",
"bevy_crevice",
"bevy_derive",
"bevy_ecs",
"bevy_math",
@ -479,7 +498,7 @@ dependencies = [
"bevy_utils",
"bevy_window",
"bitflags",
"crevice",
"codespan-reporting",
"downcast-rs",
"futures-lite",
"hex",
@ -528,12 +547,10 @@ dependencies = [
"bevy_transform",
"bevy_utils",
"bytemuck",
"crevice",
"guillotiere",
"rectangle-pack",
"serde",
"thiserror",
"wgpu",
]
[[package]]
@ -603,11 +620,9 @@ dependencies = [
"bevy_utils",
"bevy_window",
"bytemuck",
"crevice",
"serde",
"smallvec",
"stretch",
"wgpu",
]
[[package]]
@ -1038,25 +1053,6 @@ dependencies = [
"cfg-if 1.0.0",
]
[[package]]
name = "crevice"
version = "0.8.0"
dependencies = [
"bytemuck",
"crevice-derive",
"glam",
"mint",
]
[[package]]
name = "crevice-derive"
version = "0.8.0"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "crossbeam-channel"
version = "0.5.1"
@ -1371,6 +1367,7 @@ checksum = "9a5e5bb97bf9a0d9519a28cf38839cf1d6d9bb572b48e3c67202271fec2ed5e7"
dependencies = [
"core-foundation 0.6.4",
"io-kit-sys",
"js-sys",
"libc",
"libudev-sys",
"log",
@ -1379,6 +1376,7 @@ dependencies = [
"stdweb 0.4.20",
"uuid",
"vec_map",
"web-sys",
"winapi",
]
@ -1718,6 +1716,17 @@ version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
[[package]]
name = "lewton"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "777b48df9aaab155475a83a7df3070395ea1ac6902f5cd062b8f2b028075c030"
dependencies = [
"byteorder",
"ogg",
"tinyvec",
]
[[package]]
name = "libc"
version = "0.2.112"
@ -1824,26 +1833,6 @@ dependencies = [
"objc",
]
[[package]]
name = "minimp3"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "985438f75febf74c392071a975a29641b420dd84431135a6e6db721de4b74372"
dependencies = [
"minimp3-sys",
"slice-deque",
"thiserror",
]
[[package]]
name = "minimp3-sys"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e21c73734c69dc95696c9ed8926a2b393171d98b3f5f5935686a26a487ab9b90"
dependencies = [
"cc",
]
[[package]]
name = "miniz_oxide"
version = "0.3.7"
@ -2130,9 +2119,9 @@ dependencies = [
[[package]]
name = "num_cpus"
version = "1.13.0"
version = "1.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3"
checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1"
dependencies = [
"hermit-abi",
"libc",
@ -2202,6 +2191,15 @@ dependencies = [
"cc",
]
[[package]]
name = "ogg"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6951b4e8bf21c8193da321bcce9c9dd2e13c858fe078bf9054a288b419ae5d6e"
dependencies = [
"byteorder",
]
[[package]]
name = "once_cell"
version = "1.9.0"
@ -2461,7 +2459,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4d98f5e557b61525057e2bc142c8cd7f0e70d75dc32852309bec440e6e046bf9"
dependencies = [
"cpal",
"minimp3",
"lewton",
]
[[package]]
@ -2601,17 +2599,6 @@ version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5"
[[package]]
name = "slice-deque"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "31ef6ee280cdefba6d2d0b4b78a84a1c1a3f3a4cec98c2d4231c8bc225de0f25"
dependencies = [
"libc",
"mach 0.3.2",
"winapi",
]
[[package]]
name = "slotmap"
version = "1.0.6"
@ -2727,9 +2714,9 @@ checksum = "8fb1df15f412ee2e9dfc1c504260fa695c1c3f10fe9f4a6ee2d2184d7d6450e2"
[[package]]
name = "syn"
version = "1.0.82"
version = "1.0.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8daf5dd0bb60cbd4137b1b587d2fc0ae729bc07cf01cd70b36a1ed5ade3b9d59"
checksum = "23a1dfb999630e338648c83e91c59a4e9fb7620f520c3194b6b89e276f2f1959"
dependencies = [
"proc-macro2",
"quote",
@ -2774,6 +2761,21 @@ dependencies = [
"once_cell",
]
[[package]]
name = "tinyvec"
version = "1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c1c1d5a42b6245520c249549ec267180beaffcc0615401ac8e31853d4b6d8d2"
dependencies = [
"tinyvec_macros",
]
[[package]]
name = "tinyvec_macros"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
[[package]]
name = "toml"
version = "0.5.8"
@ -2829,9 +2831,9 @@ dependencies = [
[[package]]
name = "tracing-subscriber"
version = "0.3.3"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "245da694cc7fc4729f3f418b304cb57789f1bed2a78c575407ab8a23f53cb4d3"
checksum = "d5e6136799e1079699e0d9784c883e03af55cf6a1bee48fe1d79ca552c1bc36f"
dependencies = [
"ansi_term",
"lazy_static",

View file

@ -1,6 +1,9 @@
use bevy::{
app::{Events, ManualEventReader},
input::{mouse::MouseMotion, Input},
input::{
gamepad::{GamepadAxisType, GamepadEvent, GamepadEventType},
Input,
},
prelude::*,
};
@ -8,25 +11,41 @@ use bevy::{
// git@github.com:sburris0/bevy_flycam.git, b90f6fc, which is copyright 2020
// Spencer Burris
/// Keeps track of mouse motion events, pitch, and yaw
struct PlayerState {
velocity: Vec3,
}
impl Default for PlayerState {
fn default() -> Self {
PlayerState {
velocity: Vec3::ZERO,
}
}
}
#[derive(Default)]
struct InputState {
reader_motion: ManualEventReader<MouseMotion>,
event_reader: ManualEventReader<GamepadEvent>,
pitch: f32,
yaw: f32,
throttle: f32,
}
/// Mouse sensitivity and movement speed
pub struct MovementSettings {
pub sensitivity: f32,
pub speed: f32,
pub accel: f32,
pub drag: f32,
pub gravity: f32,
}
impl Default for MovementSettings {
fn default() -> Self {
Self {
sensitivity: 0.00012,
speed: 40.,
sensitivity: 1.0,
accel: 40.,
drag: 0.05,
gravity: 10.0,
}
}
}
@ -47,34 +66,17 @@ fn setup_player(mut commands: Commands) {
/// Handles keyboard input and movement
fn player_move(
keys: Res<Input<KeyCode>>,
time: Res<Time>,
settings: Res<MovementSettings>,
mut query: Query<(&FlyCam, &mut Transform)>,
state: Res<PlayerState>,
mut query: Query<&mut Transform, With<FlyCam>>,
) {
for (_camera, mut transform) in query.iter_mut() {
let mut velocity = Vec3::ZERO;
let local_z = transform.local_z();
let forward = -Vec3::new(local_z.x, 0., local_z.z);
let right = Vec3::new(local_z.z, 0., -local_z.x);
let mut transform = query.single_mut();
for key in keys.get_pressed() {
match key {
KeyCode::Up => velocity += forward,
KeyCode::Down => velocity -= forward,
KeyCode::Left => velocity -= right,
KeyCode::Right => velocity += right,
KeyCode::Space => velocity += Vec3::Y,
KeyCode::Back => velocity -= Vec3::Y,
_ => (),
}
}
let dt = time.delta_seconds();
//let down =
velocity = velocity.normalize();
if !velocity.is_nan() {
transform.translation += velocity * time.delta_seconds() * settings.speed
}
if !state.velocity.is_nan() {
transform.translation += state.velocity * dt;
}
}
@ -82,29 +84,81 @@ fn player_move(
fn player_look(
settings: Res<MovementSettings>,
windows: Res<Windows>,
mut state: ResMut<InputState>,
motion: Res<Events<MouseMotion>>,
mut query: Query<(&FlyCam, &mut Transform)>,
events: Res<Events<GamepadEvent>>,
time: Res<Time>,
mut istate: ResMut<InputState>,
mut pstate: ResMut<PlayerState>,
mut query: Query<&mut Transform, With<FlyCam>>,
) {
let window = windows.get_primary().unwrap();
for (_camera, mut transform) in query.iter_mut() {
for ev in state.reader_motion.iter(&motion) {
if window.cursor_locked() {
// Using smallest of height or width ensures equal vertical and horizontal
// sensitivity
let window_scale = window.height().min(window.width());
let window_scale = window.height().min(window.width());
let dt = time.delta_seconds();
let mut transform = query.single_mut();
let mut vel = pstate.velocity;
state.pitch -= (settings.sensitivity * ev.delta.y * window_scale).to_radians();
state.yaw -= (settings.sensitivity * ev.delta.x * window_scale).to_radians();
let accel = settings.accel * dt * istate.throttle;
//dbg!(istate.throttle);
if !pstate.velocity.is_nan() {
for GamepadEvent(_, ev) in istate.event_reader.iter(&events) {
dbg!(&istate.throttle, &ev);
// Using smallest of height or width ensures equal vertical and horizontal
// sensitivity
// state.pitch -= (settings.sensitivity * ev.delta.y *
// window_scale).to_radians();
// state.yaw -=
// (settings.sensitivity * ev.delta.x * window_scale).to_radians();
// state.pitch = state.pitch.clamp(-1.54, 1.54);
// // Order is important to prevent unintended roll
// transform.rotation = Quat::from_axis_angle(Vec3::Y, state.yaw)
// * Quat::from_axis_angle(Vec3::X, state.pitch);
dbg!(ev);
match *ev {
GamepadEventType::ButtonChanged(GamepadButtonType::RightTrigger2, val) => {
istate.throttle = -val;
}
GamepadEventType::ButtonChanged(GamepadButtonType::LeftTrigger2, val) => {
istate.throttle = val;
}
GamepadEventType::AxisChanged(GamepadAxisType::LeftStickX, val) => {
istate.yaw = -val;
}
GamepadEventType::AxisChanged(GamepadAxisType::LeftStickY, val) => {
istate.pitch = -val;
}
_ => {}
}
state.pitch = state.pitch.clamp(-1.54, 1.54);
// Order is important to prevent unintended roll
transform.rotation = Quat::from_axis_angle(Vec3::Y, state.yaw)
* Quat::from_axis_angle(Vec3::X, state.pitch);
}
vel += transform.local_z() * accel;
// drag
let v2 = vel.length_squared().min(20_000.0);
if v2 < 0.05 {
vel = Vec3::ZERO;
} else {
let drag = vel * settings.drag * v2 * time.delta_seconds();
vel -= drag;
}
} else {
vel = Vec3::ZERO;
}
let d_alt = (settings.sensitivity * dt * window_scale * istate.pitch).to_radians();
let d_az = (settings.sensitivity * dt * window_scale * istate.yaw).to_radians();
let rotation = Quat::from_rotation_y(d_az) * Quat::from_rotation_x(d_alt);
transform.rotate(rotation);
//dbg!(&vel);
pstate.velocity = vel;
}
fn cursor_grab(
@ -114,14 +168,13 @@ fn cursor_grab(
) {
let window = windows.get_primary_mut().unwrap();
if keys.just_pressed(KeyCode::L) {
window.set_cursor_lock_mode(true);
window.set_cursor_visibility(true);
let (_, mut transform) = query.single_mut();
*transform.as_mut() = transform.looking_at(Vec3::ZERO, Vec3::Y);
}
if keys.just_pressed(KeyCode::U) {
window.set_cursor_lock_mode(false);
window.set_cursor_visibility(false);
let lock = !window.cursor_locked();
window.set_cursor_lock_mode(lock);
window.set_cursor_visibility(lock);
}
}
@ -130,11 +183,12 @@ fn cursor_grab(
pub struct PlayerPlugin;
impl Plugin for PlayerPlugin {
fn build(&self, app: &mut bevy::prelude::App) {
app.init_resource::<InputState>()
app.init_resource::<PlayerState>()
.init_resource::<MovementSettings>()
.init_resource::<InputState>()
.add_startup_system(setup_player)
.add_system(player_move)
.add_system(player_look)
.add_system(player_move.label("move"))
.add_system(player_look.after("move"))
.add_system(cursor_grab);
}
}

View file

@ -17,8 +17,10 @@ fn main() {
.add_plugins(DefaultPlugins)
.add_plugin(PlayerPlugin)
.insert_resource(MovementSettings {
sensitivity: 0.00015, // default: 0.00012
speed: 12.0, // default: 12.0
sensitivity: 1.0, // default: 1.0
accel: 20.0, // default: 40.0
drag: 0.1, // default: 0.05
gravity: 10.0, // default: 10.0
})
.add_startup_system(setup.label("world"))
.add_startup_system(disable_cursor.after("world"))
@ -62,6 +64,11 @@ fn setup(
..Default::default()
};
commands.insert_resource(AmbientLight {
color: Color::PINK,
brightness: 0.08,
});
// world
commands.spawn_bundle(PbrBundle {
mesh: meshes.add(Mesh::from(shape::Icosphere {