Added support for controllers
This commit is contained in:
parent
c536a838ad
commit
1242a42f0e
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
_ => (),
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue