Skip to content

Commit 9fb68e2

Browse files
committed
Add basic support for gamepads
This currently breaks keyboard input as the gamepad is overriding the values in FpsControllerInput. Both methods either need to reach consensus or we need to be able to switch from one to the other.
1 parent 71623b2 commit 9fb68e2

File tree

1 file changed

+79
-17
lines changed

1 file changed

+79
-17
lines changed

src/controller.rs

+79-17
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use std::f32::consts::*;
2+
use std::hash::Hash;
23

3-
use bevy::{input::mouse::MouseMotion, math::Vec3Swizzles, prelude::*};
4+
use bevy::{input::mouse::MouseMotion, prelude::*};
45
use bevy_rapier3d::prelude::*;
56

67
/// Manages the FPS controllers. Executes in `PreUpdate`, after bevy's internal
@@ -34,6 +35,7 @@ impl Plugin for FpsControllerPlugin {
3435
PreUpdate,
3536
(
3637
fps_controller_input,
38+
fps_controller_gamepad_input,
3739
fps_controller_look,
3840
fps_controller_move,
3941
fps_controller_render,
@@ -113,7 +115,7 @@ pub struct FpsController {
113115
pub yaw: f32,
114116
pub ground_tick: u8,
115117
pub stop_speed: f32,
116-
pub sensitivity: f32,
118+
pub mouse_sensitivity: f32,
117119
pub enable_input: bool,
118120
pub step_offset: f32,
119121
pub key_forward: KeyCode,
@@ -126,6 +128,17 @@ pub struct FpsController {
126128
pub key_jump: KeyCode,
127129
pub key_fly: KeyCode,
128130
pub key_crouch: KeyCode,
131+
pub pad_move_x: GamepadAxisType,
132+
pub pad_move_y: GamepadAxisType,
133+
pub pad_look_x: GamepadAxisType,
134+
pub pad_look_y: GamepadAxisType,
135+
pub pad_fly_up: GamepadButtonType,
136+
pub pad_fly_down: GamepadButtonType,
137+
pub pad_jump: GamepadButtonType,
138+
pub pad_sprint: GamepadButtonType,
139+
pub pad_fly: GamepadButtonType,
140+
pub pad_crouch: GamepadButtonType,
141+
pub pad_sensitivity: f32,
129142
}
130143

131144
impl Default for FpsController {
@@ -171,7 +184,18 @@ impl Default for FpsController {
171184
key_jump: KeyCode::Space,
172185
key_fly: KeyCode::KeyF,
173186
key_crouch: KeyCode::ControlLeft,
174-
sensitivity: 0.001,
187+
mouse_sensitivity: 0.001,
188+
pad_move_x: GamepadAxisType::LeftStickX,
189+
pad_move_y: GamepadAxisType::LeftStickY,
190+
pad_look_x: GamepadAxisType::RightStickX,
191+
pad_look_y: GamepadAxisType::RightStickY,
192+
pad_fly_up: GamepadButtonType::DPadUp,
193+
pad_fly_down: GamepadButtonType::DPadDown,
194+
pad_jump: GamepadButtonType::South,
195+
pad_sprint: GamepadButtonType::LeftThumb,
196+
pad_fly: GamepadButtonType::RightThumb,
197+
pad_crouch: GamepadButtonType::East,
198+
pad_sensitivity: 0.025,
175199
}
176200
}
177201
}
@@ -199,7 +223,7 @@ pub fn fps_controller_input(
199223
for mouse_event in mouse_events.read() {
200224
mouse_delta += mouse_event.delta;
201225
}
202-
mouse_delta *= controller.sensitivity;
226+
mouse_delta *= controller.mouse_sensitivity;
203227

204228
input.pitch = (input.pitch - mouse_delta.y)
205229
.clamp(-FRAC_PI_2 + ANGLE_EPSILON, FRAC_PI_2 - ANGLE_EPSILON);
@@ -209,9 +233,9 @@ pub fn fps_controller_input(
209233
}
210234

211235
input.movement = Vec3::new(
212-
get_axis(&key_input, controller.key_right, controller.key_left),
213-
get_axis(&key_input, controller.key_up, controller.key_down),
214-
get_axis(&key_input, controller.key_forward, controller.key_back),
236+
to_axis(&key_input, controller.key_right, controller.key_left),
237+
to_axis(&key_input, controller.key_up, controller.key_down),
238+
to_axis(&key_input, controller.key_forward, controller.key_back),
215239
);
216240
input.sprint = key_input.pressed(controller.key_sprint);
217241
input.jump = key_input.pressed(controller.key_jump);
@@ -220,6 +244,51 @@ pub fn fps_controller_input(
220244
}
221245
}
222246

247+
pub fn fps_controller_gamepad_input(
248+
gamepads: Res<Gamepads>,
249+
axis_input: Res<Axis<GamepadAxis>>,
250+
button_input: Res<ButtonInput<GamepadButton>>,
251+
mut query: Query<(&FpsController, &mut FpsControllerInput)>,
252+
) {
253+
for gamepad in gamepads.iter() {
254+
// Helper functions to get axis and button values
255+
let axis = |axis_type| {
256+
axis_input
257+
.get(GamepadAxis::new(gamepad, axis_type))
258+
.unwrap()
259+
};
260+
let button = |button_type| GamepadButton::new(gamepad, button_type);
261+
262+
for (controller, mut input) in query.iter_mut() {
263+
if !controller.enable_input {
264+
continue;
265+
}
266+
267+
let move_vec = Vec2::new(axis(controller.pad_move_x), axis(controller.pad_move_y));
268+
let look_vec = Vec2::new(axis(controller.pad_look_x), axis(controller.pad_look_y))
269+
* controller.pad_sensitivity;
270+
271+
input.pitch = (input.pitch + look_vec.y)
272+
.clamp(-FRAC_PI_2 + ANGLE_EPSILON, FRAC_PI_2 - ANGLE_EPSILON);
273+
input.yaw -= look_vec.x;
274+
if input.yaw.abs() > PI {
275+
input.yaw = input.yaw.rem_euclid(TAU);
276+
}
277+
278+
let vertical_axis = to_axis(
279+
&button_input,
280+
button(controller.pad_fly_up),
281+
button(controller.pad_fly_down),
282+
);
283+
input.movement = Vec3::new(move_vec.x, vertical_axis, move_vec.y);
284+
input.sprint = button_input.pressed(button(controller.pad_sprint));
285+
input.jump = button_input.pressed(button(controller.pad_jump));
286+
input.fly = button_input.just_pressed(button(controller.pad_fly));
287+
input.crouch = button_input.pressed(button(controller.pad_crouch));
288+
}
289+
}
290+
}
291+
223292
pub fn fps_controller_look(mut query: Query<(&mut FpsController, &FpsControllerInput)>) {
224293
for (mut controller, input) in query.iter_mut() {
225294
controller.pitch = input.pitch;
@@ -516,16 +585,9 @@ fn acceleration(
516585
wish_direction * acceleration_speed
517586
}
518587

519-
fn get_pressed(key_input: &Res<ButtonInput<KeyCode>>, key: KeyCode) -> f32 {
520-
if key_input.pressed(key) {
521-
1.0
522-
} else {
523-
0.0
524-
}
525-
}
526-
527-
fn get_axis(key_input: &Res<ButtonInput<KeyCode>>, key_pos: KeyCode, key_neg: KeyCode) -> f32 {
528-
get_pressed(key_input, key_pos) - get_pressed(key_input, key_neg)
588+
/// Converts two button inputs into an f32 with a range of [-1, 1]
589+
fn to_axis<T: Copy + Eq + Send + Sync + Hash>(input: &Res<ButtonInput<T>>, pos: T, neg: T) -> f32 {
590+
input.pressed(pos) as u8 as f32 - input.pressed(neg) as u8 as f32
529591
}
530592

531593
// ██████╗ ███████╗███╗ ██╗██████╗ ███████╗██████╗

0 commit comments

Comments
 (0)