Added support for controllers
This commit is contained in:
parent
c536a838ad
commit
1242a42f0e
|
@ -13,8 +13,10 @@ use clap::{
|
||||||
use sfml::window::{
|
use sfml::window::{
|
||||||
Event,
|
Event,
|
||||||
Key,
|
Key,
|
||||||
|
joystick,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
use rusty::engine::scene::Scene;
|
use rusty::engine::scene::Scene;
|
||||||
use rusty::engine::character::Character;
|
use rusty::engine::character::Character;
|
||||||
use rusty::engine::controls::Controls;
|
use rusty::engine::controls::Controls;
|
||||||
|
@ -60,7 +62,16 @@ fn main() {
|
||||||
let resolution = parse_resolution(matches.value_of("resolution").unwrap()).unwrap();
|
let resolution = parse_resolution(matches.value_of("resolution").unwrap()).unwrap();
|
||||||
let fullscreen = matches.is_present("fullscreen");
|
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));
|
character.set_position((10.0, 0.0));
|
||||||
|
|
||||||
let mut scene = Scene::new();
|
let mut scene = Scene::new();
|
||||||
|
|
|
@ -5,7 +5,6 @@ use std::time::{
|
||||||
|
|
||||||
use sfml::system::Vector2;
|
use sfml::system::Vector2;
|
||||||
use sfml::window::Event;
|
use sfml::window::Event;
|
||||||
use sfml::window::Key;
|
|
||||||
use sfml::graphics::{
|
use sfml::graphics::{
|
||||||
IntRect,
|
IntRect,
|
||||||
FloatRect,
|
FloatRect,
|
||||||
|
@ -13,7 +12,11 @@ use sfml::graphics::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use engine::scene::Updatable;
|
use engine::scene::Updatable;
|
||||||
use engine::controls::Controls;
|
use engine::controls::{
|
||||||
|
Controls,
|
||||||
|
Action,
|
||||||
|
};
|
||||||
|
|
||||||
use engine::renderer::Drawable;
|
use engine::renderer::Drawable;
|
||||||
use engine::texture::Texture;
|
use engine::texture::Texture;
|
||||||
use engine::physics;
|
use engine::physics;
|
||||||
|
@ -158,13 +161,12 @@ impl Updatable for Character {
|
||||||
|
|
||||||
let mut force: Vector2<f32> = Vector2::new(0.0, 0.0);
|
let mut force: Vector2<f32> = Vector2::new(0.0, 0.0);
|
||||||
|
|
||||||
// Manage the input of the player
|
match self.controls {
|
||||||
if Key::Left.is_pressed() {
|
Some(ref controls) => {
|
||||||
force.x -= 1.0;
|
force += controls.direction();
|
||||||
}
|
}
|
||||||
|
|
||||||
if Key::Right.is_pressed() {
|
_ => (),
|
||||||
force.x += 1.0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(side) = Side::from_force(force) {
|
if let Some(side) = Side::from_force(force) {
|
||||||
|
@ -181,7 +183,6 @@ impl Updatable for Character {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
let duration = duration_as_f32(duration);
|
let duration = duration_as_f32(duration);
|
||||||
|
|
||||||
// Compute acceleration
|
// Compute acceleration
|
||||||
|
@ -201,22 +202,25 @@ impl Updatable for Character {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn manage_event(&mut self, event: &Event) {
|
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 {
|
match action {
|
||||||
code: Key::Return, ..
|
Some(Action::Jump(true)) => {
|
||||||
} => {
|
|
||||||
self.jump();
|
self.jump();
|
||||||
self.can_jump = false;
|
self.can_jump = false;
|
||||||
}
|
},
|
||||||
,
|
|
||||||
|
|
||||||
Event::KeyReleased {
|
Some(Action::Jump(false)) => {
|
||||||
code: Key::Return, ..
|
self.can_jump = true;
|
||||||
} => 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.
|
/// 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 {
|
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