use sfml::system::Vector2; use sfml::window::joystick::{ Axis, axis_position, is_connected, is_button_pressed, COUNT, }; use sfml::window::{ Key, Event, }; /// The different actions that a user can do. pub enum Action { /// The jump button. /// /// A bool at true means that the button was pressed, /// A bool at false means that the button was released. Jump(bool), } /// Contains the data needed to manage the controls of the player. #[derive(Copy, Clone)] pub enum Controls { /// A keyboard controller. Keyboard(KeyboardMap), /// A gamepad controller. Gamepad(GamepadMap), } impl Controls { /// Returns the default keyboard controls. pub fn default_keyboard() -> Controls { Controls::Keyboard(KeyboardMap::default()) } /// Returns the default gamepad controls from id. /// /// Returns None if the gamepad corresponding to the id is not connected. pub fn default_gamepad_from_id(id: u32) -> Option { match GamepadMap::from_id(id) { Some(map) => Some(Controls::Gamepad(map)), None => None, } } /// Returns the default gamepad controls from id. /// /// Returns None if the gamepad corresponding to the id is not connected. pub fn all_gamepads() -> Vec { GamepadMap::all() .into_iter() .map(|x| Controls::Gamepad(x)) .collect() } /// Converts an event and depending on the config, returns the corresponding action. pub fn convert(&self, event: &Event) -> Option { match self { Controls::Keyboard(ref map) => map.convert(event), Controls::Gamepad(ref map) => map.convert(event), } } /// Returns the direction of the controls. pub fn direction(&self) -> Vector2 { match self { Controls::Keyboard(ref map) => map.direction(), Controls::Gamepad(ref map) => map.direction(), } } /// Returns whether the running key is pressed. pub fn is_running(&self) -> bool { match self { Controls::Keyboard(ref map) => map.is_running(), Controls::Gamepad(ref map) => map.is_running(), } } } /// A map between keyboard keys and actions. #[derive(Copy, Clone)] pub struct KeyboardMap { /// The key corresponding to the jump button. jump_key: Key, /// The key corresponding to the run button. run_key: Key, /// The key corresponding to the up button. up_key: Key, /// The key corresponding to the left button. left_key: Key, /// The key corresponding to the right button. right_key: Key, /// The key corresponding to the down button. down_key: Key, } impl KeyboardMap { /// Creates the default keyboard config. pub fn default() -> KeyboardMap { KeyboardMap { jump_key: Key::Space, run_key: Key::LAlt, up_key: Key::Up, left_key: Key::Left, right_key: Key::Right, down_key: Key::Down, } } /// Converts an event and depending on the config, returns the corresponding action. pub fn convert(&self, event: &Event) -> Option { match event { Event::KeyPressed { code, .. } if *code == self.jump_key => Some(Action::Jump(true)), Event::KeyReleased { code, .. } if *code == self.jump_key => Some(Action::Jump(false)), _ => None, } } /// Returns the direction of the keys. pub fn direction(&self) -> Vector2 { let mut ret = Vector2::new(0.0, 0.0); const RIGHT: Vector2 = Vector2 { x: 1.0, y: 0.0 }; const UP: Vector2 = Vector2 {x: 0.0, y: 1.0}; if self.right_key.is_pressed() { ret += RIGHT; } if self.left_key.is_pressed() { ret -= RIGHT; } if self.up_key.is_pressed() { ret += UP; } if self.down_key.is_pressed() { ret -= UP; } ret } /// Returns whether the running button is held down. pub fn is_running(&self) -> bool { self.run_key.is_pressed() } } /// A map between gamepad buttons and actions. #[derive(Copy, Clone)] pub struct GamepadMap { /// Id of the gamepad. id: u32, /// Number of the jump button. jump_button: u32, /// Number of the run button. run_button: u32, /// Left / Right axis. left_right_axis: Axis, } impl GamepadMap { /// Creates the default gamepad from an id. /// /// Returns None if the gamepad corresponding to the id is not connected. pub fn from_id(id: u32) -> Option { if ! is_connected(id){ return None; } Some(GamepadMap { id: id, jump_button: 1, run_button: 2, left_right_axis: Axis::X, }) } /// Creates a vector containing all connected gamepads. pub fn all() -> Vec { let mut gamepads = vec![]; for id in 0 .. COUNT { if let Some(gamepad) = GamepadMap::from_id(id) { gamepads.push(gamepad); } } gamepads } /// Converts an event and depending on the config, returns the corresponding action. pub fn convert(&self, event: &Event) -> Option { match event { Event::JoystickButtonPressed { joystickid, button } if *joystickid == self.id && *button == self.jump_button => { Some(Action::Jump(true)) }, Event::JoystickButtonReleased { joystickid, button } if *joystickid == self.id && *button == self.jump_button => { Some(Action::Jump(false)) }, _ => None, } } /// Returns the direction of the directionnal buttons of the gamepad. pub fn direction(&self) -> Vector2 { Vector2::new( axis_position(self.id, self.left_right_axis) / 100.0, 0.0 ) } /// Returns whether the run button is held down. pub fn is_running(&self) -> bool { is_button_pressed(self.id, self.run_button) } }