11use 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:: * } ;
45use bevy_rapier3d:: prelude:: * ;
56
67/// Manages the FPS controllers. Executes in `PreUpdate`, after bevy's internal
@@ -33,7 +34,9 @@ impl Plugin for FpsControllerPlugin {
3334 app. add_systems (
3435 PreUpdate ,
3536 (
36- fps_controller_input,
37+ fps_controller_reset_input,
38+ fps_controller_keyboard_mouse_input,
39+ fps_controller_gamepad_input,
3740 fps_controller_look,
3841 fps_controller_move,
3942 fps_controller_render,
@@ -110,7 +113,7 @@ pub struct FpsController {
110113 pub yaw : f32 ,
111114 pub ground_tick : u8 ,
112115 pub stop_speed : f32 ,
113- pub sensitivity : f32 ,
116+ pub mouse_sensitivity : f32 ,
114117 pub enable_input : bool ,
115118 pub step_offset : f32 ,
116119 pub key_forward : KeyCode ,
@@ -123,6 +126,17 @@ pub struct FpsController {
123126 pub key_jump : KeyCode ,
124127 pub key_fly : KeyCode ,
125128 pub key_crouch : KeyCode ,
129+ pub pad_move_x : GamepadAxis ,
130+ pub pad_move_y : GamepadAxis ,
131+ pub pad_look_x : GamepadAxis ,
132+ pub pad_look_y : GamepadAxis ,
133+ pub pad_fly_up : GamepadButton ,
134+ pub pad_fly_down : GamepadButton ,
135+ pub pad_jump : GamepadButton ,
136+ pub pad_sprint : GamepadButton ,
137+ pub pad_fly : GamepadButton ,
138+ pub pad_crouch : GamepadButton ,
139+ pub pad_sensitivity : f32 ,
126140}
127141
128142impl Default for FpsController {
@@ -168,7 +182,18 @@ impl Default for FpsController {
168182 key_jump : KeyCode :: Space ,
169183 key_fly : KeyCode :: KeyF ,
170184 key_crouch : KeyCode :: ControlLeft ,
171- sensitivity : 0.001 ,
185+ mouse_sensitivity : 0.001 ,
186+ pad_move_x : GamepadAxis :: LeftStickX ,
187+ pad_move_y : GamepadAxis :: LeftStickY ,
188+ pad_look_x : GamepadAxis :: RightStickX ,
189+ pad_look_y : GamepadAxis :: RightStickY ,
190+ pad_fly_up : GamepadButton :: DPadUp ,
191+ pad_fly_down : GamepadButton :: DPadDown ,
192+ pad_jump : GamepadButton :: South ,
193+ pad_sprint : GamepadButton :: LeftThumb ,
194+ pad_fly : GamepadButton :: RightThumb ,
195+ pad_crouch : GamepadButton :: East ,
196+ pad_sensitivity : 0.025 ,
172197 }
173198 }
174199}
@@ -188,7 +213,13 @@ const GROUNDED_DISTANCE: f32 = 0.125;
188213
189214const SLIGHT_SCALE_DOWN : f32 = 0.9375 ;
190215
191- pub fn fps_controller_input (
216+ pub fn fps_controller_reset_input ( mut query : Query < & mut FpsControllerInput > ) {
217+ for mut input in query. iter_mut ( ) {
218+ * input = default ( ) ;
219+ }
220+ }
221+
222+ pub fn fps_controller_keyboard_mouse_input (
192223 key_input : Res < ButtonInput < KeyCode > > ,
193224 mut mouse_events : EventReader < MouseMotion > ,
194225 mut query : Query < ( & FpsController , & mut FpsControllerInput ) > ,
@@ -199,7 +230,7 @@ pub fn fps_controller_input(
199230 for mouse_event in mouse_events. read ( ) {
200231 mouse_delta += mouse_event. delta ;
201232 }
202- mouse_delta *= controller. sensitivity ;
233+ mouse_delta *= controller. mouse_sensitivity ;
203234
204235 input. pitch = ( input. pitch - mouse_delta. y )
205236 . clamp ( -FRAC_PI_2 + ANGLE_EPSILON , FRAC_PI_2 - ANGLE_EPSILON ) ;
@@ -208,22 +239,57 @@ pub fn fps_controller_input(
208239 input. yaw = input. yaw . rem_euclid ( TAU ) ;
209240 }
210241
211- 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 ) ,
242+ input. movement + = Vec3 :: new (
243+ to_axis ( & key_input, controller. key_right , controller. key_left ) ,
244+ to_axis ( & key_input, controller. key_up , controller. key_down ) ,
245+ to_axis ( & key_input, controller. key_forward , controller. key_back ) ,
215246 ) ;
216- input. sprint = key_input. pressed ( controller. key_sprint ) ;
217- input. jump = key_input. pressed ( controller. key_jump ) ;
218- input. fly = key_input. just_pressed ( controller. key_fly ) ;
219- input. crouch = key_input. pressed ( controller. key_crouch ) ;
247+ input. sprint = input. sprint || key_input. pressed ( controller. key_sprint ) ;
248+ input. jump = input. jump || key_input. pressed ( controller. key_jump ) ;
249+ input. fly = input. fly || key_input. just_pressed ( controller. key_fly ) ;
250+ input. crouch = input. crouch || key_input. pressed ( controller. key_crouch ) ;
251+ }
252+ }
253+
254+ pub fn fps_controller_gamepad_input (
255+ gamepads : Query < & Gamepad > ,
256+ mut query : Query < ( & FpsController , & mut FpsControllerInput ) > ,
257+ ) {
258+ for gamepad in gamepads. iter ( ) {
259+
260+ for ( controller, mut input) in query. iter_mut ( ) {
261+ if !controller. enable_input {
262+ continue ;
263+ }
264+
265+ // Helper function to get axis values
266+ let axis = |axis_type| gamepad. get ( axis_type) . unwrap ( ) ;
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 ( gamepad. digital ( ) , controller. pad_fly_up , controller. pad_fly_down ) ;
279+
280+ input. movement += Vec3 :: new ( move_vec. x , vertical_axis, move_vec. y ) ;
281+ input. sprint = input. sprint || gamepad. pressed ( controller. pad_sprint ) ;
282+ input. jump = input. jump || gamepad. pressed ( controller. pad_jump ) ;
283+ input. fly = input. fly || gamepad. just_pressed ( controller. pad_fly ) ;
284+ input. crouch = input. crouch || gamepad. pressed ( controller. pad_crouch ) ;
285+ }
220286 }
221287}
222288
223289pub fn fps_controller_look ( mut query : Query < ( & mut FpsController , & FpsControllerInput ) > ) {
224290 for ( mut controller, input) in query. iter_mut ( ) {
225- controller. pitch = input. pitch ;
226- controller. yaw = input. yaw ;
291+ controller. pitch + = input. pitch ;
292+ controller. yaw + = input. yaw ;
227293 }
228294}
229295
@@ -265,7 +331,7 @@ pub fn fps_controller_move(
265331 } else {
266332 controller. fly_speed
267333 } ;
268- let mut move_to_world = Mat3 :: from_euler ( EulerRot :: YXZ , input . yaw , input . pitch , 0.0 ) ;
334+ let mut move_to_world = Mat3 :: from_euler ( EulerRot :: YXZ , controller . yaw , controller . pitch , 0.0 ) ;
269335 move_to_world. z_axis *= -1.0 ; // Forward is -Z
270336 move_to_world. y_axis = Vec3 :: Y ; // Vertical movement aligned with world up
271337 velocity. linvel = move_to_world * input. movement * fly_speed;
@@ -288,7 +354,7 @@ pub fn fps_controller_move(
288354 ) ;
289355
290356 let speeds = Vec3 :: new ( controller. side_speed , 0.0 , controller. forward_speed ) ;
291- let mut move_to_world = Mat3 :: from_axis_angle ( Vec3 :: Y , input . yaw ) ;
357+ let mut move_to_world = Mat3 :: from_axis_angle ( Vec3 :: Y , controller . yaw ) ;
292358 move_to_world. z_axis *= -1.0 ; // Forward is -Z
293359 let mut wish_direction = move_to_world * ( input. movement * speeds) ;
294360 let mut wish_speed = wish_direction. length ( ) ;
@@ -543,16 +609,9 @@ fn acceleration(
543609 wish_direction * acceleration_speed
544610}
545611
546- fn get_pressed ( key_input : & Res < ButtonInput < KeyCode > > , key : KeyCode ) -> f32 {
547- if key_input. pressed ( key) {
548- 1.0
549- } else {
550- 0.0
551- }
552- }
553-
554- fn get_axis ( key_input : & Res < ButtonInput < KeyCode > > , key_pos : KeyCode , key_neg : KeyCode ) -> f32 {
555- get_pressed ( key_input, key_pos) - get_pressed ( key_input, key_neg)
612+ /// Converts two button inputs into an f32 with a range of [-1, 1]
613+ fn to_axis < T : Copy + Eq + Send + Sync + Hash > ( input : & ButtonInput < T > , pos : T , neg : T ) -> f32 {
614+ input. pressed ( pos) as u8 as f32 - input. pressed ( neg) as u8 as f32
556615}
557616
558617// ██████╗ ███████╗███╗ ██╗██████╗ ███████╗██████╗
0 commit comments