Added controller support

master
Wynd 2025-01-01 20:03:58 +02:00
parent e942867f8e
commit b72d550b4d
4 changed files with 178 additions and 16 deletions

43
src/gamepad.rs 100644
View File

@ -0,0 +1,43 @@
use bevy::{
input::gamepad::{GamepadConnection, GamepadEvent},
prelude::*,
};
pub struct GamepadPlugin;
impl Plugin for GamepadPlugin {
fn build(&self, app: &mut App) {
app.add_systems(Startup, setup);
}
}
#[derive(Debug, Resource)]
pub struct GamepadOne(pub Gamepad);
fn setup(
mut commands: Commands,
gamepad1: Option<Res<GamepadOne>>,
mut gamepad_events: EventReader<GamepadEvent>,
) {
for event in gamepad_events.read() {
let GamepadEvent::Connection(conn) = event
else {
continue;
};
match &conn.connection {
GamepadConnection::Connected(info) => {
if gamepad1.is_none() {
commands.insert_resource(GamepadOne(conn.gamepad));
}
}
GamepadConnection::Disconnected => {
if let Some(GamepadOne(id)) = gamepad1.as_deref() {
if *id == conn.gamepad {
commands.remove_resource::<GamepadOne>();
}
}
}
}
}
}

View File

@ -2,10 +2,13 @@ use std::path::Path;
use bevy::{
asset::{io::AssetSourceId, AssetPath},
ecs::query::QueryIter,
prelude::*,
};
use crate::{player::Player, score::Score, GameStartEvent, GameState, START_POSITION};
use crate::{
gamepad::GamepadOne, player::Player, score::Score, GameStartEvent, GameState, START_POSITION,
};
pub struct HUDPlugin;
@ -149,32 +152,75 @@ pub struct StartButton;
pub struct StartMenuUI;
fn start_button_logic(
current_state: Res<State<GameState>>,
mut state: ResMut<NextState<GameState>>,
mut score: ResMut<Score>,
gamepads: Res<ButtonInput<GamepadButton>>,
gamepad1: Option<Res<GamepadOne>>,
mut button: Query<(&Interaction, &mut BorderColor), With<StartButton>>,
mut player_query: Query<(&mut Transform, &mut Visibility), With<Player>>,
mut ui_elems_query: Query<&mut Visibility, (With<StartMenuUI>, Without<Player>)>,
mut score_text_query: Query<&mut Text, With<ScoreText>>,
) {
if current_state.get() == &GameState::Playing {
return;
};
let mut score_text = score_text_query.single_mut();
let (mut player_transform, mut player_visibility) = player_query.single_mut();
if let Some(gamepad) = gamepad1.as_deref() {
let start_btn = GamepadButton {
gamepad: gamepad.0,
button_type: GamepadButtonType::Start,
};
if gamepads.pressed(start_btn) {
start_game(
&mut score_text,
&mut score,
&mut state,
&mut ui_elems_query,
&mut player_visibility,
&mut player_transform,
);
}
}
let (interaction, mut border_color) = button.single_mut();
match *interaction {
Interaction::Pressed => {
let mut score_text = score_text_query.single_mut();
score.0 = 0;
score_text.sections[0].value = format!("{}", score.0);
state.set(GameState::Playing);
let (mut player_transform, mut player_visibility) = player_query.single_mut();
for mut elem in &mut ui_elems_query {
*elem = Visibility::Hidden;
}
*player_visibility = Visibility::Visible;
player_transform.translation = START_POSITION;
start_game(
&mut score_text,
&mut score,
&mut state,
&mut ui_elems_query,
&mut player_visibility,
&mut player_transform,
);
}
Interaction::Hovered => border_color.0 = Color::WHITE,
Interaction::None => border_color.0 = Color::BLACK,
}
}
fn start_game(
score_text: &mut Text,
score: &mut Score,
state: &mut NextState<GameState>,
ui_elems: &mut Query<&mut Visibility, (With<StartMenuUI>, Without<Player>)>,
player_visibility: &mut Visibility,
player_transform: &mut Transform,
) {
score.0 = 0;
score_text.sections[0].value = format!("{}", score.0);
state.set(GameState::Playing);
for mut elem in ui_elems {
*elem = Visibility::Hidden;
}
*player_visibility = Visibility::Visible;
player_transform.translation = START_POSITION;
}

View File

@ -8,6 +8,7 @@ use bevy::{
window::{WindowMode, WindowResolution},
};
use common::mouse::{Mouse, MousePlugin};
use gamepad::GamepadPlugin;
use hud::HUDPlugin;
use level::LevelPlugin;
use player::PlayerPlugin;
@ -15,6 +16,7 @@ use score::ScorePlugin;
mod common;
mod enemy;
mod gamepad;
mod hud;
mod level;
mod player;
@ -89,6 +91,7 @@ fn main() {
// EmbeddedAssetPlugin,
LevelPlugin,
MousePlugin,
GamepadPlugin,
))
.init_state::<GameState>()
.add_event::<GameOverEvent>()

View File

@ -1,12 +1,17 @@
use std::f32::consts::PI;
use bevy::{prelude::*, render::view::VisibilityPlugin};
use bevy::{
input::gamepad::{GamepadConnection, GamepadEvent},
prelude::*,
render::view::VisibilityPlugin,
};
use crate::{
common::{
animation::{AnimationBundle, AnimationIndices, AnimationPlugin, AnimationTimer},
velocity::Velocity,
},
gamepad::GamepadOne,
level::{Collider, UnitBundle},
GameState, SCREEN_HEIGHT, SCREEN_WIDTH, START_POSITION,
};
@ -66,11 +71,19 @@ fn setup(
fn move_player(
keys: Res<ButtonInput<KeyCode>>,
axes: Res<Axis<GamepadAxis>>,
gamepads: Res<ButtonInput<GamepadButton>>,
gamepad1: Option<Res<GamepadOne>>,
mut query: Query<(&mut Transform, &mut Velocity), With<Player>>,
window: Query<&Window>,
) {
let (mut transform, mut velocity) = query.single_mut();
velocity.0 = Vec2::ZERO;
if let Some(gamepad) = gamepad1.as_deref() {
handle_gamepad_movement(&axes, gamepad, &gamepads, &mut velocity);
};
if keys.pressed(KeyCode::ArrowRight) {
velocity.x += 1.0;
}
@ -95,3 +108,60 @@ fn move_player(
let screen_size: Vec3 = window.physical_size().as_vec2().extend(1.0);
transform.translation = transform.translation.clamp(Vec3::ZERO, screen_size);
}
fn handle_gamepad_movement(
axes: &Axis<GamepadAxis>,
gamepad: &GamepadOne,
gamepads: &Res<ButtonInput<GamepadButton>>,
velocity: &mut Velocity,
) {
let axis_lx = GamepadAxis {
gamepad: gamepad.0,
axis_type: GamepadAxisType::LeftStickX,
};
let axis_ly = GamepadAxis {
gamepad: gamepad.0,
axis_type: GamepadAxisType::LeftStickY,
};
if let (Some(x), Some(y)) = (axes.get(axis_lx), axes.get(axis_ly)) {
let left_stick = Vec2::new(x, y);
if left_stick.length() > 0.25 {
*velocity = Velocity(left_stick);
return;
}
}
let up_btn = GamepadButton {
gamepad: gamepad.0,
button_type: GamepadButtonType::DPadUp,
};
let down_btn = GamepadButton {
gamepad: gamepad.0,
button_type: GamepadButtonType::DPadDown,
};
let left_btn = GamepadButton {
gamepad: gamepad.0,
button_type: GamepadButtonType::DPadLeft,
};
let right_btn = GamepadButton {
gamepad: gamepad.0,
button_type: GamepadButtonType::DPadRight,
};
if gamepads.pressed(right_btn) {
velocity.x += 1.0;
}
if gamepads.pressed(left_btn) {
velocity.x -= 1.0;
}
if gamepads.pressed(up_btn) {
velocity.y += 1.0;
}
if gamepads.pressed(down_btn) {
velocity.y -= 1.0;
}
}