fn join(
mut commands: Commands,
mut joined_players: ResMut<JoinedPlayers>,
gamepads: Res<Gamepads>,
button_inputs: Res<ButtonInput<GamepadButton>>,
mut texture_atlases: ResMut<Assets<TextureAtlasLayout>>,
asset_server: Res<AssetServer>,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<ColorMaterial>>,
) {
for gamepad in gamepads.iter() {
// Join the game when both bumpers (L+R) on the controller are pressed
// We drop down the Bevy's input to get the input from each gamepad
if button_inputs.pressed(GamepadButton::new(gamepad, GamepadButtonType::LeftTrigger))
&& button_inputs.pressed(GamepadButton::new(gamepad, GamepadButtonType::RightTrigger))
{
// Make sure a player can not join twice
if !joined_players.0.contains_key(&gamepad) {
println!("Player {} has joined the game!", gamepad.id);
let input_map = InputMap::default()
.insert_multiple([
(PlayerAction::Left, GamepadButtonType::DPadLeft),
(PlayerAction::Right, GamepadButtonType::DPadRight),
(PlayerAction::Up, GamepadButtonType::DPadUp),
(PlayerAction::Down, GamepadButtonType::DPadDown),
(PlayerAction::Throw, GamepadButtonType::RightTrigger2),
(PlayerAction::Dash, GamepadButtonType::South),
(PlayerAction::Start, GamepadButtonType::Start),
(PlayerAction::Disconnect, GamepadButtonType::Select),
])
.insert(PlayerAction::Move, DualAxis::left_stick())
.insert(PlayerAction::Aim, DualAxis::right_stick())
// Make sure to set the gamepad or all gamepads will be used!
.set_gamepad(gamepad)
.build();
let player = spawn_player(
&mut commands,
&asset_server,
&mut texture_atlases,
input_map,
gamepad,
);
// Insert the created player and its gamepad to the hashmap of joined players
// Since uniqueness was already checked above, we can insert here unchecked
joined_players.0.insert_unique_unchecked(gamepad, player);
}
}
}
}
This is my spawn_player:
pub fn spawn_player(
commands: &mut Commands,
asset_server: &Res<AssetServer>,
texture_atlases_layouts: &mut ResMut<Assets<TextureAtlasLayout>>,
input_map: InputMap<PlayerAction>,
gamepad: Gamepad,
) -> Entity {
let texture = asset_server.load("duckyatlas.png");
let layout = TextureAtlasLayout::from_grid(UVec2::new(64, 64), 5, 3, None, None);
let texture_atlas_layout = texture_atlases_layouts.add(layout);
// Use only the subset of sprites in the sheet that make up the run animation
let animation_indices = AnimationIndices {
first: 10,
last: 13,
};
let player = commands
.spawn(PlayerBundle {
player: Player {
player_id: gamepad.id, //make this dynamic
lives: 3,
gamepad,
have_ball: false,
},
input_manager: InputManagerBundle {
input_map,
..Default::default()
},
sprite: SpriteSheetBundle {
texture,
atlas: TextureAtlas {
layout: texture_atlas_layout,
index: animation_indices.first,
},
transform: Transform::from_xyz(50.0, -250., 2.0),
..default()
},
..default()
})
.insert(RigidBody::KinematicPositionBased)
.insert(Ccd::enabled())
.insert(KinematicCharacterController::default())
.insert(Collider::ball(10.0))
.insert(ActiveEvents::COLLISION_EVENTS)
.insert(GravityScale(0.0))
.id();
return player;
}
Test function with bug?
fn test_bug(action_query: Query<(&ActionState<PlayerAction>, &Player)>) {
for (action_state, player) in action_query.iter() {
if action_state.just_pressed(&PlayerAction::Throw) {
println!("Player {} dash!", player.gamepad.id);
}
}
}
What you expected to happen
When RightTrigger is pressed on a gamepad, that players gamepad id is printed.
What actually happened
When pressing a RightTrigger, all connected gamepads id is printed:
Additional information
I this is my move function.
The dualaxis stick movement works as expected(Only one player moving.)
The dpad movement is the same as the bug. (all players move).
fn move_player(
mut query: Query<
(
&ActionState<PlayerAction>,
&mut Transform,
&mut Velocity,
&mut PlayerDirection,
&mut Sprite,
&mut TextureAtlas,
),
With<Player>,
>,
time_step: Res<Time<Fixed>>,
) {
for (
action_state,
mut player_transform,
mut velocity,
mut direction,
mut sprite,
mut texture_atlas,
) in query.iter_mut()
{
let mut horizontal = 0.0;
let mut vertical = 0.0;
if action_state.pressed(&PlayerAction::Up) {
vertical += 1.0;
}
if action_state.pressed(&PlayerAction::Down) {
vertical -= 1.0;
}
if action_state.pressed(&PlayerAction::Left) {
horizontal -= 1.0;
sprite.flip_x = true;
}
if action_state.pressed(&PlayerAction::Right) {
horizontal += 1.0;
sprite.flip_x = false;
}
let mut new_player_position_horizontal =
player_transform.translation.x + horizontal * PLAYER_SPEED * time_step.delta_seconds();
let mut new_player_position_vertical =
player_transform.translation.y + vertical * PLAYER_SPEED * time_step.delta_seconds();
if action_state.pressed(&PlayerAction::Move) {
// We're working with gamepads, so we want to defensively ensure that we're using the clamped values
let axis_pair = action_state.clamped_axis_pair(&PlayerAction::Move).unwrap();
velocity.0.x = axis_pair.x();
velocity.0.y = axis_pair.y();
direction.direction.x = axis_pair.x();
direction.direction.y = axis_pair.y();
new_player_position_horizontal = player_transform.translation.x
+ velocity.0.x * PLAYER_SPEED * time_step.delta_seconds();
new_player_position_vertical = player_transform.translation.y
+ velocity.0.y * PLAYER_SPEED * time_step.delta_seconds();
// if moved left or right flip sprite
if velocity.0.x != 0.0 {
sprite.flip_x = velocity.0.x < 0.0;
}
// idle animation or run animation
if velocity.0.x != 0.0 || velocity.0.y != 0.0 {
if texture_atlas.index < 4 || texture_atlas.index > 7 {
texture_atlas.index = 4;
}
} else {
if texture_atlas.index < 10 || texture_atlas.index > 13 {
texture_atlas.index = 10;
}
}
}
// Update the player position,
// making sure it doesn't cause the player to leave the arena
let left_bound = LEFT_WALL + WALL_THICKNESS / 2.0 + PLAYER_SIZE.x / 2.0 + PLAYER_PADDING;
let right_bound = RIGHT_WALL - WALL_THICKNESS / 2.0 - PLAYER_SIZE.x / 2.0 - PLAYER_PADDING;
let top_bound = TOP_WALL - WALL_THICKNESS / 2.0 - PLAYER_SIZE.y / 2.0 - PLAYER_PADDING;
let bottom_bound =
BOTTOM_WALL + WALL_THICKNESS / 2.0 + PLAYER_SIZE.y / 2.0 + PLAYER_PADDING;
player_transform.translation.x =
new_player_position_horizontal.clamp(left_bound, right_bound);
player_transform.translation.y =
new_player_position_vertical.clamp(bottom_bound, top_bound);
}
}
Its acting like the .set_gamepad() for the input map is not working?
I'd appreciate some help :heart:
Version
bevy = {version = "0.14" ,features = ["dynamic_linking","bevy_state"]} leafwing-input-manager = "0.14"
Operating system & version
popos 22.04
What you did
This is my function for join:
This is my spawn_player:
Test function with bug?
What you expected to happen
When RightTrigger is pressed on a gamepad, that players gamepad id is printed.
What actually happened
When pressing a RightTrigger, all connected gamepads id is printed:![image](https://github.com/Leafwing-Studios/leafwing-input-manager/assets/56272436/6a81f31f-9ef2-494f-b034-baed053b73e9)
Additional information
I this is my move function. The dualaxis stick movement works as expected(Only one player moving.) The dpad movement is the same as the bug. (all players move).
Its acting like the .set_gamepad() for the input map is not working? I'd appreciate some help :heart:
Thanks!