use crate::bitfield; use crate::framework::context::Context; use crate::framework::error::GameResult; use crate::framework::gamepad::{self, Button, PlayerControllerInputType}; use crate::game::shared_game_state::SharedGameState; use crate::input::player_controller::PlayerController; use crate::game::player::TargetPlayer; bitfield! { #[derive(Clone, Copy)] pub struct KeyState(u16); impl Debug; pub left, set_left: 0; pub right, set_right: 1; pub up, set_up: 2; pub down, set_down: 3; pub map, set_map: 4; pub inventory, set_inventory: 5; pub jump, set_jump: 6; pub shoot, set_shoot: 7; pub next_weapon, set_next_weapon: 8; pub prev_weapon, set_prev_weapon: 9; pub escape, set_escape: 10; pub skip, set_skip: 11; pub strafe, set_strafe: 12; pub menu_ok, set_menu_ok: 13; pub menu_back, set_menu_back: 14; } #[derive(Clone)] pub struct GamepadController { gamepad_id: u32, target: TargetPlayer, state: KeyState, old_state: KeyState, trigger: KeyState, rumble_state: Option, rumble_enabled: bool, } #[derive(Clone)] pub struct RumbleState { pub low_freq: u16, pub hi_freq: u16, pub ticks: u32, } impl GamepadController { pub fn new(gamepad_id: u32, target: TargetPlayer) -> GamepadController { GamepadController { gamepad_id, target, state: KeyState(0), old_state: KeyState(0), trigger: KeyState(0), rumble_state: None, rumble_enabled: false, } } pub fn set_rumble_enabled(&mut self, enabled: bool) { self.rumble_enabled = enabled; } } impl PlayerController for GamepadController { fn update(&mut self, state: &mut SharedGameState, ctx: &mut Context) -> GameResult { let button_map = match self.target { TargetPlayer::Player1 => &state.settings.player1_controller_button_map, TargetPlayer::Player2 => &state.settings.player2_controller_button_map, }; self.state.set_up(gamepad::is_active(ctx, self.gamepad_id, &button_map.up)); self.state.set_down(gamepad::is_active(ctx, self.gamepad_id, &button_map.down)); self.state.set_left(gamepad::is_active(ctx, self.gamepad_id, &button_map.left)); self.state.set_right(gamepad::is_active(ctx, self.gamepad_id, &button_map.right)); self.state.set_map(gamepad::is_active(ctx, self.gamepad_id, &button_map.map)); self.state.set_inventory(gamepad::is_active(ctx, self.gamepad_id, &button_map.inventory)); self.state.set_jump(gamepad::is_active(ctx, self.gamepad_id, &button_map.jump)); self.state.set_shoot(gamepad::is_active(ctx, self.gamepad_id, &button_map.shoot)); self.state.set_next_weapon(gamepad::is_active(ctx, self.gamepad_id, &button_map.next_weapon)); self.state.set_prev_weapon(gamepad::is_active(ctx, self.gamepad_id, &button_map.prev_weapon)); self.state.set_escape(gamepad::is_active( ctx, self.gamepad_id, &PlayerControllerInputType::ButtonInput(Button::Start), )); self.state.set_skip(gamepad::is_active(ctx, self.gamepad_id, &button_map.skip)); self.state.set_strafe(gamepad::is_active(ctx, self.gamepad_id, &button_map.strafe)); self.state.set_menu_ok(gamepad::is_active(ctx, self.gamepad_id, &button_map.menu_ok)); self.state.set_menu_back(gamepad::is_active(ctx, self.gamepad_id, &button_map.menu_back)); if let Some(rumble_data) = &self.rumble_state { gamepad::set_rumble( ctx, state, self.gamepad_id, rumble_data.low_freq, rumble_data.hi_freq, rumble_data.ticks, )?; self.rumble_state = None; } Ok(()) } fn update_trigger(&mut self) { let mut trigger = self.state.0 ^ self.old_state.0; trigger &= self.state.0; self.old_state = self.state; self.trigger = KeyState(trigger); } fn move_up(&self) -> bool { self.state.up() } fn move_left(&self) -> bool { self.state.left() } fn move_down(&self) -> bool { self.state.down() } fn move_right(&self) -> bool { self.state.right() } fn prev_weapon(&self) -> bool { self.state.prev_weapon() } fn next_weapon(&self) -> bool { self.state.next_weapon() } fn map(&self) -> bool { self.state.map() } fn inventory(&self) -> bool { self.state.inventory() } fn jump(&self) -> bool { self.state.jump() } fn shoot(&self) -> bool { self.state.shoot() } fn skip(&self) -> bool { self.state.skip() } fn strafe(&self) -> bool { self.state.strafe() } fn trigger_up(&self) -> bool { self.trigger.up() } fn trigger_left(&self) -> bool { self.trigger.left() } fn trigger_down(&self) -> bool { self.trigger.down() } fn trigger_right(&self) -> bool { self.trigger.right() } fn trigger_prev_weapon(&self) -> bool { self.trigger.prev_weapon() } fn trigger_next_weapon(&self) -> bool { self.trigger.next_weapon() } fn trigger_map(&self) -> bool { self.trigger.map() } fn trigger_inventory(&self) -> bool { self.trigger.inventory() } fn trigger_jump(&self) -> bool { self.trigger.jump() } fn trigger_shoot(&self) -> bool { self.trigger.shoot() } fn trigger_skip(&self) -> bool { self.trigger.skip() } fn trigger_strafe(&self) -> bool { self.trigger.strafe() } fn trigger_menu_ok(&self) -> bool { self.trigger.menu_ok() } fn trigger_menu_back(&self) -> bool { self.trigger.menu_back() || self.trigger.escape() } fn trigger_menu_pause(&self) -> bool { self.trigger.escape() } fn look_up(&self) -> bool { self.state.up() } fn look_left(&self) -> bool { self.state.left() } fn look_down(&self) -> bool { self.state.down() } fn look_right(&self) -> bool { self.state.right() } fn move_analog_x(&self) -> f64 { if self.state.left() && self.state.right() { 0.0 } else if self.state.left() { -1.0 } else if self.state.right() { 1.0 } else { 0.0 } } fn move_analog_y(&self) -> f64 { if self.state.up() && self.state.down() { 0.0 } else if self.state.up() { -1.0 } else if self.state.down() { 1.0 } else { 0.0 } } fn set_rumble(&mut self, low_freq: u16, hi_freq: u16, ticks: u32) { if !self.rumble_enabled { return; } if !self.rumble_state.is_none() { return; } self.rumble_state = Some(RumbleState { low_freq, hi_freq, ticks }); } }