Added support for controllers

This commit is contained in:
Thomas Forgione 2018-10-13 18:30:44 +02:00
parent c536a838ad
commit 1242a42f0e
No known key found for this signature in database
GPG Key ID: 63D3E1A00D54FD76
3 changed files with 256 additions and 23 deletions

View File

@ -13,8 +13,10 @@ use clap::{
use sfml::window::{
Event,
Key,
joystick,
};
use rusty::engine::scene::Scene;
use rusty::engine::character::Character;
use rusty::engine::controls::Controls;
@ -60,7 +62,16 @@ fn main() {
let resolution = parse_resolution(matches.value_of("resolution").unwrap()).unwrap();
let fullscreen = matches.is_present("fullscreen");
let mut character = Character::with_controls(Controls::new());
joystick::update();
let gamepads = Controls::all_gamepads();
let controls = if gamepads.is_empty() {
Controls::default_keyboard()
} else {
gamepads[0].clone()
};
let mut character = Character::with_controls(controls);
character.set_position((10.0, 0.0));
let mut scene = Scene::new();

View File

@ -5,7 +5,6 @@ use std::time::{
use sfml::system::Vector2;
use sfml::window::Event;
use sfml::window::Key;
use sfml::graphics::{
IntRect,
FloatRect,
@ -13,7 +12,11 @@ use sfml::graphics::{
};
use engine::scene::Updatable;
use engine::controls::Controls;
use engine::controls::{
Controls,
Action,
};
use engine::renderer::Drawable;
use engine::texture::Texture;
use engine::physics;
@ -158,13 +161,12 @@ impl Updatable for Character {
let mut force: Vector2<f32> = Vector2::new(0.0, 0.0);
// Manage the input of the player
if Key::Left.is_pressed() {
force.x -= 1.0;
}
match self.controls {
Some(ref controls) => {
force += controls.direction();
}
if Key::Right.is_pressed() {
force.x += 1.0;
_ => (),
}
if let Some(side) = Side::from_force(force) {
@ -181,7 +183,6 @@ impl Updatable for Character {
}
let duration = duration_as_f32(duration);
// Compute acceleration
@ -201,22 +202,25 @@ impl Updatable for Character {
}
fn manage_event(&mut self, event: &Event) {
match event {
let action = if let Some(ref controls) = self.controls {
controls.convert(event)
} else {
None
};
Event::KeyPressed {
code: Key::Return, ..
} => {
match action {
Some(Action::Jump(true)) => {
self.jump();
self.can_jump = false;
}
,
},
Event::KeyReleased {
code: Key::Return, ..
} => self.can_jump = true,
Some(Action::Jump(false)) => {
self.can_jump = true;
}
_ => (),
}
}
}

View File

@ -1,14 +1,232 @@
use sfml::system::Vector2;
use sfml::window::joystick::{
Axis,
axis_position,
is_connected,
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.
pub struct Controls {
#[derive(Copy, Clone)]
pub enum Controls {
/// A keyboard controller.
Keyboard(KeyboardMap),
/// A gamepad controller.
Gamepad(GamepadMap),
}
impl Controls {
/// Creates the default controls.
pub fn new() -> Controls {
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(),
}
}
}
/// 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 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,
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
}
}
/// 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,
/// 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,
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
)
}
}