free-rusty-maker/src/engine/controls/mod.rs

260 lines
6.2 KiB
Rust

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<Controls> {
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<Controls> {
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<Action> {
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<f32> {
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<Action> {
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<f32> {
let mut ret = Vector2::new(0.0, 0.0);
const RIGHT: Vector2<f32> = Vector2 { x: 1.0, y: 0.0 };
const UP: Vector2<f32> = 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<GamepadMap> {
if ! is_connected(id){
return None;
}
Some(GamepadMap {
id: id,
jump_button: 1,
run_button: 0,
left_right_axis: Axis::X,
})
}
/// Creates a vector containing all connected gamepads.
pub fn all() -> Vec<GamepadMap> {
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<Action> {
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<f32> {
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)
}
}