From c565692e6300be8b6a2ef9ff3c01e19df2df3a7b Mon Sep 17 00:00:00 2001 From: Astro Date: Sat, 15 Jan 2022 02:09:12 +0100 Subject: [PATCH] local multiplayer --- src/input.rs | 108 +++++++++++++++++++++++++++++++++++ src/main.rs | 7 ++- src/player.rs | 154 +++++++++++++++++++++++++++++--------------------- 3 files changed, 202 insertions(+), 67 deletions(-) create mode 100644 src/input.rs diff --git a/src/input.rs b/src/input.rs new file mode 100644 index 0000000..87321c6 --- /dev/null +++ b/src/input.rs @@ -0,0 +1,108 @@ +use std::collections::HashSet; +use bevy::{ + input::gamepad::{Gamepad, GamepadAxisType, GamepadButtonType, GamepadEvent, GamepadEventType}, + prelude::*, +}; + +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +pub enum Source { + KeyboardRight, + KeyboardLeft, + Gamepad(Gamepad), +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +pub enum Key { + Up, + Down, + Left, + Right, + Jump, +} + +const KEYBOARD_KEYS: &[(KeyCode, Source, Key)] = &[ + (KeyCode::Up, Source::KeyboardRight, Key::Up), + (KeyCode::Down, Source::KeyboardRight, Key::Down), + (KeyCode::Left, Source::KeyboardRight, Key::Left), + (KeyCode::Right, Source::KeyboardRight, Key::Right), + (KeyCode::Return, Source::KeyboardRight, Key::Jump), + (KeyCode::W, Source::KeyboardLeft, Key::Up), + (KeyCode::S, Source::KeyboardLeft, Key::Down), + (KeyCode::A, Source::KeyboardLeft, Key::Left), + (KeyCode::D, Source::KeyboardLeft, Key::Right), + (KeyCode::Space, Source::KeyboardLeft, Key::Jump), +]; + +const GAMEPAD_KEYS: &[(GamepadButtonType, Key)] = &[ + (GamepadButtonType::DPadUp, Key::Up), + (GamepadButtonType::DPadDown, Key::Down), + (GamepadButtonType::DPadLeft, Key::Left), + (GamepadButtonType::DPadRight, Key::Right), + (GamepadButtonType::South, Key::Jump), +]; + +#[derive(Default)] +pub struct InputState(pub HashSet<(Source, Key)>); + +pub fn setup(mut commands: Commands) { + commands.insert_resource(InputState::default()); +} + +pub fn handle( + keyboard: Res>, + mut gamepad_event: EventReader, + mut state: ResMut, +) { + // handle keyboard + for (key_code, source, key) in KEYBOARD_KEYS { + if keyboard.pressed(*key_code) { + state.0.insert((source.clone(), *key)); + } else { + state.0.remove(&(source.clone(), *key)); + } + } + + // handle gamepads + for event in gamepad_event.iter() { + match event { + GamepadEvent(gamepad, GamepadEventType::ButtonChanged(button, value)) => { + if let Some((_, key)) = GAMEPAD_KEYS.iter().find(|(button_, _)| { + button == button_ + }) { + if *value > 0.01 { + state.0.insert((Source::Gamepad(*gamepad), *key)); + } else { + state.0.remove(&(Source::Gamepad(*gamepad), *key)); + } + } + } + GamepadEvent(gamepad, GamepadEventType::AxisChanged(GamepadAxisType::DPadX, value)) | + GamepadEvent(gamepad, GamepadEventType::AxisChanged(GamepadAxisType::LeftStickX, value)) => { + if *value < -0.01 { + state.0.insert((Source::Gamepad(*gamepad), Key::Left)); + state.0.remove(&(Source::Gamepad(*gamepad), Key::Right)); + } else if *value > 0.01 { + state.0.insert((Source::Gamepad(*gamepad), Key::Right)); + state.0.remove(&(Source::Gamepad(*gamepad), Key::Left)); + } else { + state.0.remove(&(Source::Gamepad(*gamepad), Key::Left)); + state.0.remove(&(Source::Gamepad(*gamepad), Key::Right)); + } + } + GamepadEvent(gamepad, GamepadEventType::AxisChanged(GamepadAxisType::DPadY, value)) | + GamepadEvent(gamepad, GamepadEventType::AxisChanged(GamepadAxisType::LeftStickY, value)) => { + if *value < -0.01 { + state.0.insert((Source::Gamepad(*gamepad), Key::Down)); + state.0.remove(&(Source::Gamepad(*gamepad), Key::Up)); + } else if *value > 0.01 { + state.0.insert((Source::Gamepad(*gamepad), Key::Up)); + state.0.remove(&(Source::Gamepad(*gamepad), Key::Down)); + } else { + state.0.remove(&(Source::Gamepad(*gamepad), Key::Up)); + state.0.remove(&(Source::Gamepad(*gamepad), Key::Down)); + } + } + _ => {} + } + } +} diff --git a/src/main.rs b/src/main.rs index f553454..26d35cb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,6 +5,7 @@ use bevy::{ }; use heron::prelude::*; +mod input; mod camera; mod map; mod player; @@ -23,13 +24,15 @@ fn main() { .add_plugin(PhysicsPlugin::default()) .insert_resource(Gravity::from(Vec3::new(0.0, -9.81, 0.0))) .insert_resource(ClearColor(Color::rgb(0.7, 0.7, 1.0))) + .add_startup_system(input::setup) + .add_system(input::handle.label("input")) .add_startup_system(camera::setup) .add_system(camera::track_players) .add_startup_system(map::setup) .add_system(map::build) .add_system(map::collide) - .add_startup_system(player::setup) - .add_system(player::input) + .add_system(player::spawn_player) + .add_system(player::input.after("input")) .add_system(exit_on_escape) // .add_system(log_collisions) .run(); diff --git a/src/player.rs b/src/player.rs index 1b6b972..449f40a 100644 --- a/src/player.rs +++ b/src/player.rs @@ -1,20 +1,37 @@ use std::f32::consts::PI; use bevy::prelude::*; use heron::prelude::*; +use rand::prelude::*; use crate::{ + input::{InputState, Key, Source as InputSource}, map::GroundContact, Layer, }; #[derive(Component)] pub struct Player { + input_source: InputSource, rotation: f32, } -pub fn setup( +pub fn spawn_player( mut commands: Commands, + players: Query<&Player>, + input: Res, asset_server: Res, ) { + let input_source = match input.0.iter().find(|(input_source, key)| + if *key == Key::Jump { + ! players.iter().any(|player| player.input_source == *input_source) + } else { + false + } + ) { + Some((input_source, _)) => input_source, + None => return, + }; + println!("New input_source: {:?}", input_source); + let mesh1 = asset_server.load("Mini-Game Variety Pack/Models/Characters/gltf/character_duck.gltf#Mesh0/Primitive0"); let mesh2 = asset_server.load("Mini-Game Variety Pack/Models/Characters/gltf/character_duck.gltf#Mesh0/Primitive1"); let mesh3 = asset_server.load("Mini-Game Variety Pack/Models/Characters/gltf/character_duck.gltf#Mesh0/Primitive2"); @@ -23,7 +40,8 @@ pub fn setup( let material2 = asset_server.load("Mini-Game Variety Pack/Models/Characters/gltf/character_duck.gltf#Material1"); let material3 = asset_server.load("Mini-Game Variety Pack/Models/Characters/gltf/character_duck.gltf#Material2"); - let transform = Transform::from_xyz(0.0, 12.0, 0.0); + let mut rng = rand::thread_rng(); + let transform = Transform::from_xyz(rng.gen_range(-3.0..3.0), 5.0, rng.gen_range(-3.0..3.0)); commands.spawn() .insert(RigidBody::Dynamic) .insert(CollisionLayers::none() @@ -36,12 +54,13 @@ pub fn setup( }) .insert(PhysicMaterial { restitution: 0.0, - density: 8.0, + density: 12.0, friction: 1.0, }) .insert(RotationConstraints::lock()) .insert(Velocity::default()) .insert(Player { + input_source: input_source.clone(), rotation: 0.0, }) .insert(GroundContact::default()) @@ -73,70 +92,75 @@ pub fn setup( }); } -pub fn input(time: Res