Skip to content

Commit

Permalink
Add type b button mapping for controller.
Browse files Browse the repository at this point in the history
  • Loading branch information
Ramirisu committed Sep 11, 2024
1 parent caec8ee commit 45e6baf
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 43 deletions.
20 changes: 10 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,16 @@ A Classic Tetris (NES Tetris) clone written in BEVY/RUST.

## Keybindings

| Menu | In Game | Keyboard | Controller (NES) |
| :--------- | :------------------------ | :--------------: | :--------------: |
| Move Up | || |
| Move Down | Soft Drop || |
| Move Left | Move Left || |
| Move Right | Move Right || |
| | Rotate Clockwisely | X | A |
| Back | Rotate Counterclockwisely | Z | B |
| Start | Pause/Resume | Enter | Start |
| Soft Reset | Soft Reset | Left Shift / Esc | Select |
| Menu | In Game | Keyboard | Controller Type A (NES) | Controller Type B (NES) |
| :--------- | :------------------------ | :--------------: | :---------------------: | :---------------------: |
| Move Up | || | |
| Move Down | Soft Drop || | |
| Move Left | Move Left || | |
| Move Right | Move Right || | |
| | Rotate Clockwisely | X | A | B |
| Back | Rotate Counterclockwisely | Z | B | Y |
| Start | Pause/Resume | Enter | Start | Start |
| Soft Reset | Soft Reset | Left Shift / Esc | Select | Select |

## Build & Run

Expand Down
41 changes: 34 additions & 7 deletions src/game_option_menu/plugin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::{
app_state::AppState,
audio::plugin::PlaySoundEvent,
game::{drop_speed::DropSpeed, transition::Transition},
inputs::PlayerInputs,
inputs::{ControllerType, PlayerInputs},
level_menu::plugin::LevelMenuData,
logo::{load_logo_images, TETRIS_BITMAP},
utility::despawn_all,
Expand Down Expand Up @@ -41,21 +41,23 @@ enum GameOptionMenuState {
Transition,
Linecap,
DropSpeed,
ControllerType,
#[cfg(not(target_arch = "wasm32"))]
WindowMode,
}

impl GameOptionMenuState {
pub fn iter() -> std::slice::Iter<'static, GameOptionMenuState> {
#[cfg(not(target_arch = "wasm32"))]
type ArrayType = [GameOptionMenuState; 5];
type ArrayType = [GameOptionMenuState; 6];
#[cfg(target_arch = "wasm32")]
type ArrayType = [GameOptionMenuState; 4];
type ArrayType = [GameOptionMenuState; 5];
const STATES: ArrayType = [
GameOptionMenuState::Tetris,
GameOptionMenuState::Transition,
GameOptionMenuState::Linecap,
GameOptionMenuState::DropSpeed,
GameOptionMenuState::ControllerType,
#[cfg(not(target_arch = "wasm32"))]
GameOptionMenuState::WindowMode,
];
Expand Down Expand Up @@ -180,6 +182,7 @@ fn setup_screen(mut commands: Commands, mut image_assets: ResMut<Assets<Image>>)
fn update_ui_system(
mut query: Query<(&mut Text, &GameOptionEntityMarker)>,
game_option_menu_data: Res<GameOptionMenuData>,
controller_type: Res<ControllerType>,
) {
query.iter_mut().for_each(|(mut text, marker)| {
let selected = marker.0 == game_option_menu_data.state;
Expand Down Expand Up @@ -224,6 +227,13 @@ fn update_ui_system(
DropSpeed::Locked => text.sections[1].value = fopt("LOCKED", true, false),
};
}
GameOptionMenuState::ControllerType => {
text.sections[0].value = fname("CONTROLLER TYPE");
match *controller_type {
ControllerType::TypeA => text.sections[1].value = fopt("TYPE A", false, true),
ControllerType::TypeB => text.sections[1].value = fopt("TYPE B", true, false),
};
}
#[cfg(not(target_arch = "wasm32"))]
GameOptionMenuState::WindowMode => {
text.sections[0].value = fname("WINDOW MODE");
Expand All @@ -248,6 +258,7 @@ fn handle_input_system(
player_inputs: Res<PlayerInputs>,
mut game_option_menu_data: ResMut<GameOptionMenuData>,
mut level_menu_data: ResMut<LevelMenuData>,
mut controller_type: ResMut<ControllerType>,
mut app_state: ResMut<NextState<AppState>>,
mut e_play_sound: EventWriter<PlaySoundEvent>,
#[cfg(not(target_arch = "wasm32"))] mut window: Query<&mut Window>,
Expand All @@ -266,7 +277,7 @@ fn handle_input_system(
}
#[cfg(target_arch = "wasm32")]
{
game_option_menu_data.state = GameOptionMenuState::Linecap;
game_option_menu_data.state = GameOptionMenuState::ControllerType;
}
e_play_sound.send(PlaySoundEvent::MoveCursor);
} else if player_inputs.down.0 {
Expand Down Expand Up @@ -332,6 +343,22 @@ fn handle_input_system(
if player_inputs.up.0 {
game_option_menu_data.state = GameOptionMenuState::Linecap;
e_play_sound.send(PlaySoundEvent::MoveCursor);
} else if player_inputs.down.0 {
game_option_menu_data.state = GameOptionMenuState::ControllerType;
e_play_sound.send(PlaySoundEvent::MoveCursor);
}
if player_inputs.right.0 {
game_option_menu_data.drop_speed = DropSpeed::Locked;
e_play_sound.send(PlaySoundEvent::MoveCursor);
} else if player_inputs.left.0 {
game_option_menu_data.drop_speed = DropSpeed::Level;
e_play_sound.send(PlaySoundEvent::MoveCursor);
}
}
GameOptionMenuState::ControllerType => {
if player_inputs.up.0 {
game_option_menu_data.state = GameOptionMenuState::DropSpeed;
e_play_sound.send(PlaySoundEvent::MoveCursor);
} else if player_inputs.down.0 {
#[cfg(not(target_arch = "wasm32"))]
{
Expand All @@ -344,17 +371,17 @@ fn handle_input_system(
e_play_sound.send(PlaySoundEvent::MoveCursor);
}
if player_inputs.right.0 {
game_option_menu_data.drop_speed = DropSpeed::Locked;
*controller_type = ControllerType::TypeB;
e_play_sound.send(PlaySoundEvent::MoveCursor);
} else if player_inputs.left.0 {
game_option_menu_data.drop_speed = DropSpeed::Level;
*controller_type = ControllerType::TypeA;
e_play_sound.send(PlaySoundEvent::MoveCursor);
}
}
#[cfg(not(target_arch = "wasm32"))]
GameOptionMenuState::WindowMode => {
if player_inputs.up.0 {
game_option_menu_data.state = GameOptionMenuState::DropSpeed;
game_option_menu_data.state = GameOptionMenuState::ControllerType;
e_play_sound.send(PlaySoundEvent::MoveCursor);
} else if player_inputs.down.0 {
game_option_menu_data.state = GameOptionMenuState::Tetris;
Expand Down
87 changes: 61 additions & 26 deletions src/inputs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,27 @@ use bevy::prelude::*;
use crate::controller::Controller;

pub fn setup(app: &mut App) {
app.insert_resource(PlayerInputs::default())
app.insert_resource(ControllerType::default())
.insert_resource(PlayerInputs::default())
.add_systems(Update, update_player_inputs);
}

fn update_player_inputs(
keys: Res<ButtonInput<KeyCode>>,
buttons: Res<ButtonInput<GamepadButton>>,
controller: Res<Controller>,
controller_type: Res<ControllerType>,
mut player_inputs: ResMut<PlayerInputs>,
) {
*player_inputs =
PlayerInputs::with_keyboard(&keys) | PlayerInputs::with_gamepads(&buttons, &controller);
*player_inputs = PlayerInputs::with_keyboard(&keys)
| PlayerInputs::with_gamepads(&buttons, &controller, *controller_type);
}

#[derive(Default, Clone, Copy, Resource)]
pub enum ControllerType {
#[default]
TypeA,
TypeB,
}

#[derive(Clone, Copy, Resource)]
Expand All @@ -23,10 +32,8 @@ pub struct PlayerInputs {
pub down: (bool, bool),
pub left: (bool, bool),
pub right: (bool, bool),
pub a: (bool, bool), // DPad::East
pub b: (bool, bool), // DPad::South
pub x: (bool, bool), // DPad::North
pub y: (bool, bool), // DPad::West
pub a: (bool, bool),
pub b: (bool, bool),
pub start: bool,
pub select: bool,

Expand All @@ -42,8 +49,6 @@ impl PlayerInputs {
right: (false, false),
a: (false, false),
b: (false, false),
x: (false, false),
y: (false, false),
start: false,
select: false,
soft_reset: false,
Expand Down Expand Up @@ -76,30 +81,37 @@ impl PlayerInputs {
inputs.just_pressed(KeyCode::KeyZ),
inputs.pressed(KeyCode::KeyZ),
),
x: (
inputs.just_pressed(KeyCode::KeyS),
inputs.pressed(KeyCode::KeyS),
),
y: (
inputs.just_pressed(KeyCode::KeyA),
inputs.pressed(KeyCode::KeyA),
),
start: inputs.just_pressed(KeyCode::Enter),
select: inputs.just_pressed(KeyCode::ShiftLeft),
soft_reset: inputs.just_pressed(KeyCode::ShiftLeft)
|| inputs.just_pressed(KeyCode::Escape),
}
}

pub fn with_gamepads(buttons: &ButtonInput<GamepadButton>, controller: &Controller) -> Self {
pub fn with_gamepads(
buttons: &ButtonInput<GamepadButton>,
controller: &Controller,
controller_type: ControllerType,
) -> Self {
let mut inputs = Self::new();
for gamepad in &controller.gamepads {
inputs |= Self::with_gamepad(buttons, *gamepad);
inputs |= Self::with_gamepad(buttons, *gamepad, controller_type);
}
inputs
}

fn with_gamepad(buttons: &ButtonInput<GamepadButton>, gamepad: Gamepad) -> Self {
fn with_gamepad(
buttons: &ButtonInput<GamepadButton>,
gamepad: Gamepad,
controller_type: ControllerType,
) -> Self {
match controller_type {
ControllerType::TypeA => Self::with_gamepad_type_a(buttons, gamepad),
ControllerType::TypeB => Self::with_gamepad_type_b(buttons, gamepad),
}
}

fn with_gamepad_type_a(buttons: &ButtonInput<GamepadButton>, gamepad: Gamepad) -> Self {
Self {
up: (
buttons.just_pressed(Self::gamepad_button(gamepad, GamepadButtonType::DPadUp)),
Expand All @@ -125,11 +137,36 @@ impl PlayerInputs {
buttons.just_pressed(Self::gamepad_button(gamepad, GamepadButtonType::South)),
buttons.pressed(Self::gamepad_button(gamepad, GamepadButtonType::South)),
),
x: (
buttons.just_pressed(Self::gamepad_button(gamepad, GamepadButtonType::North)),
buttons.pressed(Self::gamepad_button(gamepad, GamepadButtonType::North)),
start: buttons.just_pressed(Self::gamepad_button(gamepad, GamepadButtonType::Start)),
select: buttons.just_pressed(Self::gamepad_button(gamepad, GamepadButtonType::Select)),
soft_reset: buttons
.just_pressed(Self::gamepad_button(gamepad, GamepadButtonType::Select)),
}
}

fn with_gamepad_type_b(buttons: &ButtonInput<GamepadButton>, gamepad: Gamepad) -> Self {
Self {
up: (
buttons.just_pressed(Self::gamepad_button(gamepad, GamepadButtonType::DPadUp)),
buttons.pressed(Self::gamepad_button(gamepad, GamepadButtonType::DPadUp)),
),
y: (
down: (
buttons.just_pressed(Self::gamepad_button(gamepad, GamepadButtonType::DPadDown)),
buttons.pressed(Self::gamepad_button(gamepad, GamepadButtonType::DPadDown)),
),
left: (
buttons.just_pressed(Self::gamepad_button(gamepad, GamepadButtonType::DPadLeft)),
buttons.pressed(Self::gamepad_button(gamepad, GamepadButtonType::DPadLeft)),
),
right: (
buttons.just_pressed(Self::gamepad_button(gamepad, GamepadButtonType::DPadRight)),
buttons.pressed(Self::gamepad_button(gamepad, GamepadButtonType::DPadRight)),
),
a: (
buttons.just_pressed(Self::gamepad_button(gamepad, GamepadButtonType::South)),
buttons.pressed(Self::gamepad_button(gamepad, GamepadButtonType::South)),
),
b: (
buttons.just_pressed(Self::gamepad_button(gamepad, GamepadButtonType::West)),
buttons.pressed(Self::gamepad_button(gamepad, GamepadButtonType::West)),
),
Expand Down Expand Up @@ -171,8 +208,6 @@ impl std::ops::BitOr for PlayerInputs {
right: (self.right.0 | rhs.right.0, self.right.1 | rhs.right.1),
a: (self.a.0 | rhs.a.0, self.a.1 | rhs.a.1),
b: (self.b.0 | rhs.b.0, self.b.1 | rhs.b.1),
x: (self.x.0 | rhs.x.0, self.x.1 | rhs.x.1),
y: (self.y.0 | rhs.y.0, self.y.1 | rhs.y.1),
start: self.start | rhs.start,
select: self.select | rhs.select,
soft_reset: self.soft_reset | rhs.soft_reset,
Expand Down

0 comments on commit 45e6baf

Please sign in to comment.