use std::collections::HashSet; use bevy::{ input::gamepad::{Gamepad, GamepadAxisType, GamepadButtonType, GamepadEvent, GamepadEventType}, prelude::*, }; #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub enum Source { KeyboardRight, KeyboardLeft, Gamepad(Gamepad), } #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub enum Key { Up, Down, Left, Right, Jump, } const KEYBOARD_KEYS: &[(KeyCode, Source, Key)] = &[ (KeyCode::Up, Source::KeyboardRight, Key::Up), (KeyCode::Down, Source::KeyboardRight, Key::Down), (KeyCode::Left, Source::KeyboardRight, Key::Left), (KeyCode::Right, Source::KeyboardRight, Key::Right), (KeyCode::Return, Source::KeyboardRight, Key::Jump), (KeyCode::W, Source::KeyboardLeft, Key::Up), (KeyCode::S, Source::KeyboardLeft, Key::Down), (KeyCode::A, Source::KeyboardLeft, Key::Left), (KeyCode::D, Source::KeyboardLeft, Key::Right), (KeyCode::Space, Source::KeyboardLeft, Key::Jump), ]; const GAMEPAD_KEYS: &[(GamepadButtonType, Key)] = &[ (GamepadButtonType::DPadUp, Key::Up), (GamepadButtonType::DPadDown, Key::Down), (GamepadButtonType::DPadLeft, Key::Left), (GamepadButtonType::DPadRight, Key::Right), (GamepadButtonType::South, Key::Jump), ]; #[derive(Default)] pub struct InputState(pub HashSet<(Source, Key)>); pub fn setup(mut commands: Commands) { commands.insert_resource(InputState::default()); } pub fn handle( keyboard: Res>, mut gamepad_event: EventReader, mut state: ResMut, ) { // handle keyboard for (key_code, source, key) in KEYBOARD_KEYS { if keyboard.pressed(*key_code) { state.0.insert((source.clone(), *key)); } else { state.0.remove(&(source.clone(), *key)); } } // handle gamepads for event in gamepad_event.iter() { match event { GamepadEvent(gamepad, GamepadEventType::ButtonChanged(button, value)) => { if let Some((_, key)) = GAMEPAD_KEYS.iter().find(|(button_, _)| { button == button_ }) { if *value > 0.01 { state.0.insert((Source::Gamepad(*gamepad), *key)); } else { state.0.remove(&(Source::Gamepad(*gamepad), *key)); } } } GamepadEvent(gamepad, GamepadEventType::AxisChanged(GamepadAxisType::DPadX, value)) | GamepadEvent(gamepad, GamepadEventType::AxisChanged(GamepadAxisType::LeftStickX, value)) => { if *value < -0.01 { state.0.insert((Source::Gamepad(*gamepad), Key::Left)); state.0.remove(&(Source::Gamepad(*gamepad), Key::Right)); } else if *value > 0.01 { state.0.insert((Source::Gamepad(*gamepad), Key::Right)); state.0.remove(&(Source::Gamepad(*gamepad), Key::Left)); } else { state.0.remove(&(Source::Gamepad(*gamepad), Key::Left)); state.0.remove(&(Source::Gamepad(*gamepad), Key::Right)); } } GamepadEvent(gamepad, GamepadEventType::AxisChanged(GamepadAxisType::DPadY, value)) | GamepadEvent(gamepad, GamepadEventType::AxisChanged(GamepadAxisType::LeftStickY, value)) => { if *value < -0.01 { state.0.insert((Source::Gamepad(*gamepad), Key::Down)); state.0.remove(&(Source::Gamepad(*gamepad), Key::Up)); } else if *value > 0.01 { state.0.insert((Source::Gamepad(*gamepad), Key::Up)); state.0.remove(&(Source::Gamepad(*gamepad), Key::Down)); } else { state.0.remove(&(Source::Gamepad(*gamepad), Key::Up)); state.0.remove(&(Source::Gamepad(*gamepad), Key::Down)); } } _ => {} } } }