forked from bevyengine/bevy
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
examples: Factor out flying camera controller
- Loading branch information
Showing
2 changed files
with
160 additions
and
134 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
use bevy::{ | ||
core::Time, | ||
ecs::prelude::*, | ||
input::{mouse::MouseMotion, Input}, | ||
math::{EulerRot, Quat, Vec2, Vec3}, | ||
prelude::{KeyCode, Transform}, | ||
render2::camera::Camera, | ||
}; | ||
|
||
pub struct CameraController { | ||
pub enabled: bool, | ||
pub sensitivity: f32, | ||
pub key_forward: KeyCode, | ||
pub key_back: KeyCode, | ||
pub key_left: KeyCode, | ||
pub key_right: KeyCode, | ||
pub key_up: KeyCode, | ||
pub key_down: KeyCode, | ||
pub key_run: KeyCode, | ||
pub walk_speed: f32, | ||
pub run_speed: f32, | ||
pub friction: f32, | ||
pub pitch: f32, | ||
pub yaw: f32, | ||
pub velocity: Vec3, | ||
} | ||
|
||
impl CameraController { | ||
pub fn print_usage(&self) { | ||
println!( | ||
" {:?}/{:?}/{:?}/{:?}\t- forward/back/strafe left/right | ||
{:?}/{:?}\t\t- up/down | ||
{:?}\t- run/fly faster", | ||
self.key_forward, | ||
self.key_back, | ||
self.key_left, | ||
self.key_right, | ||
self.key_up, | ||
self.key_down, | ||
self.key_run, | ||
); | ||
} | ||
} | ||
|
||
impl Default for CameraController { | ||
fn default() -> Self { | ||
Self { | ||
enabled: true, | ||
sensitivity: 0.5, | ||
key_forward: KeyCode::W, | ||
key_back: KeyCode::S, | ||
key_left: KeyCode::A, | ||
key_right: KeyCode::D, | ||
key_up: KeyCode::E, | ||
key_down: KeyCode::Q, | ||
key_run: KeyCode::LShift, | ||
walk_speed: 10.0, | ||
run_speed: 30.0, | ||
friction: 0.5, | ||
pitch: 0.0, | ||
yaw: 0.0, | ||
velocity: Vec3::ZERO, | ||
} | ||
} | ||
} | ||
|
||
pub fn camera_controller( | ||
time: Res<Time>, | ||
mut mouse_events: EventReader<MouseMotion>, | ||
key_input: Res<Input<KeyCode>>, | ||
mut query: Query<(&mut Transform, &mut CameraController), With<Camera>>, | ||
) { | ||
let dt = time.delta_seconds(); | ||
|
||
// Handle mouse input | ||
let mut mouse_delta = Vec2::ZERO; | ||
for mouse_event in mouse_events.iter() { | ||
mouse_delta += mouse_event.delta; | ||
} | ||
|
||
for (mut transform, mut options) in query.iter_mut() { | ||
if !options.enabled { | ||
continue; | ||
} | ||
|
||
// Handle key input | ||
let mut axis_input = Vec3::ZERO; | ||
if key_input.pressed(options.key_forward) { | ||
axis_input.z += 1.0; | ||
} | ||
if key_input.pressed(options.key_back) { | ||
axis_input.z -= 1.0; | ||
} | ||
if key_input.pressed(options.key_right) { | ||
axis_input.x += 1.0; | ||
} | ||
if key_input.pressed(options.key_left) { | ||
axis_input.x -= 1.0; | ||
} | ||
if key_input.pressed(options.key_up) { | ||
axis_input.y += 1.0; | ||
} | ||
if key_input.pressed(options.key_down) { | ||
axis_input.y -= 1.0; | ||
} | ||
|
||
// Apply movement update | ||
if axis_input != Vec3::ZERO { | ||
let max_speed = if key_input.pressed(options.key_run) { | ||
options.run_speed | ||
} else { | ||
options.walk_speed | ||
}; | ||
options.velocity = axis_input.normalize() * max_speed; | ||
} else { | ||
let friction = options.friction.clamp(0.0, 1.0); | ||
options.velocity *= 1.0 - friction; | ||
if options.velocity.length_squared() < 1e-6 { | ||
options.velocity = Vec3::ZERO; | ||
} | ||
} | ||
let forward = transform.forward(); | ||
let right = transform.right(); | ||
transform.translation += options.velocity.x * dt * right | ||
+ options.velocity.y * dt * Vec3::Y | ||
+ options.velocity.z * dt * forward; | ||
|
||
if mouse_delta != Vec2::ZERO { | ||
// Apply look update | ||
let (pitch, yaw) = ( | ||
(options.pitch - mouse_delta.y * 0.5 * options.sensitivity * dt).clamp( | ||
-0.99 * std::f32::consts::FRAC_PI_2, | ||
0.99 * std::f32::consts::FRAC_PI_2, | ||
), | ||
options.yaw - mouse_delta.x * options.sensitivity * dt, | ||
); | ||
transform.rotation = Quat::from_euler(EulerRot::ZYX, 0.0, yaw, pitch); | ||
options.pitch = pitch; | ||
options.yaw = yaw; | ||
} | ||
} | ||
} |