From df84ef60dab6dba0582a647f42663a3248d88cbb Mon Sep 17 00:00:00 2001 From: jacopograndi Date: Fri, 5 Aug 2022 16:26:39 +0200 Subject: trainwreck --- Cargo.lock | 16 ++++ Cargo.toml | 3 +- launch_2p.sh | 4 +- src/main.rs | 295 +++++++++++++++++++++++++++++++++++++---------------------- 4 files changed, 207 insertions(+), 111 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0d8296e..10c2ed8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -137,6 +137,9 @@ name = "arrayvec" version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" +dependencies = [ + "serde", +] [[package]] name = "ash" @@ -609,6 +612,7 @@ dependencies = [ "log", "nalgebra", "rapier2d", + "serde", ] [[package]] @@ -929,6 +933,9 @@ name = "bit-vec" version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" +dependencies = [ + "serde", +] [[package]] name = "bitfield-rle" @@ -1916,6 +1923,7 @@ checksum = "e6012d540c5baa3589337a98ce73408de9b5a25ec9fc2c6fd6be8f0d39e0ca5a" dependencies = [ "autocfg", "hashbrown 0.11.2", + "serde", ] [[package]] @@ -1969,6 +1977,7 @@ dependencies = [ "bevy", "bevy_ggrs", "bevy_rapier2d", + "bincode", "bytemuck", "ggrs", "serde", @@ -2262,6 +2271,7 @@ dependencies = [ "num-complex", "num-rational", "num-traits", + "serde", "simba", "typenum", ] @@ -2427,6 +2437,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ae39348c8bc5fbd7f40c727a9925f03517afd2ab27d46702108b6a7e5414c19" dependencies = [ "num-traits", + "serde", ] [[package]] @@ -2648,10 +2659,12 @@ dependencies = [ "bitflags", "downcast-rs", "either", + "indexmap", "nalgebra", "num-derive", "num-traits", "rustc-hash", + "serde", "simba", "slab", "smallvec", @@ -2837,11 +2850,13 @@ dependencies = [ "bitflags", "crossbeam", "downcast-rs", + "indexmap", "nalgebra", "num-derive", "num-traits", "parry2d", "rustc-hash", + "serde", "simba", ] @@ -3046,6 +3061,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13a2609e876d4f77f6ab7ff5254fc39b4f1927ba8e6db3d18be7c32534d3725e" dependencies = [ "approx", + "libm", "num-complex", "num-traits", "paste", diff --git a/Cargo.toml b/Cargo.toml index 609e9af..b95538d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] bevy = { version = "0.8", features = ["dynamic"] } -bevy_rapier2d = "0.16.0" +bevy_rapier2d = { version = "0.16.0", features = ["enhanced-determinism", "serde-serialize"] } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" @@ -15,3 +15,4 @@ bevy_ggrs = { git = "https://github.com/paxsethorld/bevy_ggrs", rev = "bc78d31" ggrs = { git = "https://github.com/gschup/ggrs", features = ["sync-send"] } bytemuck = "1.11.0" structopt = "0.3.26" +bincode = "1.3.3" diff --git a/launch_2p.sh b/launch_2p.sh index 14fd8a7..6759993 100755 --- a/launch_2p.sh +++ b/launch_2p.sh @@ -1,4 +1,4 @@ #! /usr/bin/bash -cargo run -- --local-port=40000 --players localhost 127.0.0.1:40001 & -cargo run -- --local-port=40001 --players localhost 127.0.0.1:40001 & +alacritty --hold -e cargo run -- --local-port=40000 --players localhost 127.0.0.1:40001 & (sleep 1 && +alacritty --hold -e cargo run -- --local-port=40001 --players 127.0.0.1:40000 localhost) & diff --git a/src/main.rs b/src/main.rs index 1074319..7131c68 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,12 +8,16 @@ use bevy::{prelude::*, render::camera::ScalingMode, window::WindowResized}; use bevy_rapier2d::{pipeline::CollisionEvent::*, prelude::*}; -use bevy_ggrs::{GGRSPlugin, SessionType}; -use ggrs::{Config, PlayerHandle, PlayerType, SessionBuilder, UdpNonBlockingSocket}; +use bevy_ggrs::{GGRSPlugin, Rollback, RollbackIdProvider, SessionType}; +use ggrs::{ + Config, InputStatus, P2PSession, PlayerHandle, PlayerType, SessionBuilder, SpectatorSession, + SyncTestSession, UdpNonBlockingSocket, +}; use bytemuck::{Pod, Zeroable}; use std::net::SocketAddr; +use bincode::{deserialize, serialize}; use structopt::StructOpt; #[derive(Debug)] @@ -24,39 +28,9 @@ impl Config for GGRSConfig { type Address = SocketAddr; } -#[repr(C)] -#[derive(Copy, Clone, PartialEq, Pod, Zeroable)] -pub struct BoxInput { - pub inp: u8, -} - -const FPS: usize = 60; +const FPS: usize = 10; const ROLLBACK_DEFAULT: &str = "rollback_default"; -const INPUT_UP: u8 = 1 << 0; -const INPUT_DOWN: u8 = 1 << 1; -const INPUT_LEFT: u8 = 1 << 2; -const INPUT_RIGHT: u8 = 1 << 3; - -pub fn input(_handle: In, keyboard_input: Res>) -> BoxInput { - let mut input: u8 = 0; - - if keyboard_input.pressed(KeyCode::W) { - input |= INPUT_UP; - } - if keyboard_input.pressed(KeyCode::A) { - input |= INPUT_LEFT; - } - if keyboard_input.pressed(KeyCode::S) { - input |= INPUT_DOWN; - } - if keyboard_input.pressed(KeyCode::D) { - input |= INPUT_RIGHT; - } - - BoxInput { inp: input } -} - // structopt will read command line parameters for u #[derive(StructOpt)] struct Opt { @@ -105,12 +79,17 @@ fn main() -> Result<(), Box> { GGRSPlugin::::new() .with_update_frequency(FPS) .with_input_system(input) - .register_rollback_type::() - .register_rollback_type::() + .register_rollback_type::() + .register_rollback_type::() + .register_rollback_type::() .with_rollback_schedule( Schedule::default().with_stage( ROLLBACK_DEFAULT, - SystemStage::parallel() + SystemStage::single_threaded() + .with_system(physics_deser) + .with_system(movement) + .with_system(shoot) + .with_system(hits) .with_system_set(RapierPhysicsPlugin::<()>::get_systems( PhysicsStages::SyncBackend, )) @@ -122,7 +101,8 @@ fn main() -> Result<(), Box> { )) .with_system_set(RapierPhysicsPlugin::<()>::get_systems( PhysicsStages::DetectDespawn, - )), + )) + .with_system(physics_ser), ), ) .build(&mut app); @@ -136,24 +116,50 @@ fn main() -> Result<(), Box> { .insert_resource(sess) .insert_resource(SessionType::P2PSession) .add_plugins(DefaultPlugins) - .add_startup_system(spawn_camera) + .add_startup_system(physics_init) .add_startup_system(setup) - .add_plugin(LogDiagnosticsPlugin::default()) - .add_plugin(FrameTimeDiagnosticsPlugin::default()) + .add_startup_system(spawn_camera) + //.add_plugin(LogDiagnosticsPlugin::default()) + //.add_plugin(FrameTimeDiagnosticsPlugin::default()) .add_plugin( RapierPhysicsPlugin::::pixels_per_meter(100.0).with_default_system_setup(false), ) - .add_plugin(RapierDebugRenderPlugin::default()) - .add_system_to_stage(CoreStage::Update, movement) - .add_system_to_stage(CoreStage::Update, shoot) + //.add_plugin(RapierDebugRenderPlugin::default()) .add_system_to_stage(CoreStage::PostUpdate, camera_follow) - .add_system_to_stage(CoreStage::PostUpdate, hits) .add_system(window_resized_event) .run(); Ok(()) } +#[derive(Default, Reflect, Component)] +struct SerPhysics { + pub ser: Vec, +} + +fn physics_init( + mut commands: Commands, + context: Res, + mut rip: ResMut, +) { + commands + .spawn() + .insert(SerPhysics { + ser: bincode::serialize(context.into_inner()).unwrap(), + }) + .insert(Rollback::new(rip.next_id())); +} + +fn physics_ser(mut ser_query: Query<&mut SerPhysics>, context: Res) { + ser_query.single_mut().ser = bincode::serialize(context.into_inner()).unwrap(); +} + +fn physics_deser(ser_query: Query<&SerPhysics>, mut commands: Commands) { + commands.remove_resource::(); + commands + .insert_resource(bincode::deserialize::(&ser_query.single().ser).unwrap()); +} + fn window_resized_event( mut events: EventReader, mut window: ResMut, @@ -167,11 +173,18 @@ fn window_resized_event( fn camera_follow( player_query: Query<(&Player, &Transform)>, mut camera_query: Query<&mut Transform, (Without, With)>, + p2p_session: Option>>, ) { - let (_, transform) = player_query.single(); - let mut camera_transform = camera_query.single_mut(); - camera_transform.translation.x = transform.translation.x; - camera_transform.translation.y = transform.translation.y; + let handles = p2p_session.unwrap().local_player_handles(); + if handles.len() > 0 { + let (_, transform) = player_query + .iter() + .find(|(p, _)| p.handle == handles[0]) + .unwrap(); + let mut camera_transform = camera_query.single_mut(); + camera_transform.translation.x = transform.translation.x; + camera_transform.translation.y = transform.translation.y; + } } fn spawn_camera(mut commands: Commands) { @@ -205,30 +218,86 @@ fn hits( } } -#[derive(Component)] +#[derive(Component, Default, Reflect)] pub struct Bullet; -#[derive(Component)] +#[derive(Component, Default, Reflect)] pub struct Player { - speed: f32, - radius: f32, + pub handle: usize, + pub speed: f32, + pub radius: f32, +} + +#[repr(C)] +#[derive(Copy, Clone, PartialEq, Pod, Zeroable)] +pub struct BoxInput { + pub inp: u8, + pub sx: u8, + pub sy: u8, +} + +const INPUT_UP: u8 = 1 << 0; +const INPUT_DOWN: u8 = 1 << 1; +const INPUT_LEFT: u8 = 1 << 2; +const INPUT_RIGHT: u8 = 1 << 3; + +pub fn input(_handle: In, keyboard_input: Res>) -> BoxInput { + let mut input: u8 = 0; + + if keyboard_input.pressed(KeyCode::W) { + input |= INPUT_UP; + } + if keyboard_input.pressed(KeyCode::A) { + input |= INPUT_LEFT; + } + if keyboard_input.pressed(KeyCode::S) { + input |= INPUT_DOWN; + } + if keyboard_input.pressed(KeyCode::D) { + input |= INPUT_RIGHT; + } + + let mut x: u8 = 127; + let mut y: u8 = 127; + if keyboard_input.pressed(KeyCode::Up) { + y = 255; + } + if keyboard_input.pressed(KeyCode::Down) { + y = 0; + } + if keyboard_input.pressed(KeyCode::Left) { + x = 0; + } + if keyboard_input.pressed(KeyCode::Right) { + x = 255; + } + + BoxInput { + inp: input, + sx: x, + sy: y, + } } -fn movement(mut player_query: Query<(&mut Player, &mut Velocity)>, keyboard: Res>) { +fn movement( + mut player_query: Query<(&mut Player, &mut Velocity)>, + inputs: Res>, +) { for (player, mut rb_vels) in player_query.iter_mut() { + let input = inputs[player.handle as usize].0.inp; let mut acc = Vec2::new(0.0, 0.0); - if keyboard.pressed(KeyCode::W) { - acc.y += 1.0; - } - if keyboard.pressed(KeyCode::S) { + if input & INPUT_UP != 0 && input & INPUT_DOWN == 0 { acc.y -= 1.0; } - if keyboard.pressed(KeyCode::A) { + if input & INPUT_UP == 0 && input & INPUT_DOWN != 0 { acc.x -= 1.0; } - if keyboard.pressed(KeyCode::D) { + if input & INPUT_LEFT != 0 && input & INPUT_RIGHT == 0 { acc.x += 1.0; } + if input & INPUT_LEFT == 0 && input & INPUT_RIGHT != 0 { + acc.x -= 1.0; + } if acc.length_squared() > 0.0 { acc /= acc.length(); } @@ -238,23 +307,15 @@ fn movement(mut player_query: Query<(&mut Player, &mut Velocity)>, keyboard: Res fn shoot( player_query: Query<(&Player, &Transform, &Velocity)>, - keyboard: Res>, + inputs: Res>, mut commands: Commands, + mut rip: ResMut, ) { for (player, player_transform, _rb_vels) in player_query.iter() { - let mut acc = Vec2::new(0.0, 0.0); - if keyboard.pressed(KeyCode::Up) { - acc.y += 1.0; - } - if keyboard.pressed(KeyCode::Down) { - acc.y -= 1.0; - } - if keyboard.pressed(KeyCode::Left) { - acc.x -= 1.0; - } - if keyboard.pressed(KeyCode::Right) { - acc.x += 1.0; - } + let input = inputs[player.handle as usize].0; + let sx: f32 = (input.sx as f32) - 127.0 / 256.0; + let sy: f32 = (input.sy as f32) - 127.0 / 256.0; + let mut acc = Vec2::new(sx, sy); if acc.length_squared() > 0.0 { acc /= acc.length(); let head = Vec3::new(acc.x, acc.y, 0.0) * (2.0 + player.radius + 3.0); @@ -285,7 +346,8 @@ fn shoot( .insert(Ccd::enabled()) .insert(Velocity::linear(acc * 1000.0)) .insert(CollisionGroups::new(0b010, 0b101)) - .insert(ActiveEvents::COLLISION_EVENTS); + .insert(ActiveEvents::COLLISION_EVENTS) + .insert(Rollback::new(rip.next_id())); } } } @@ -368,7 +430,14 @@ fn setup_map(mut commands: Commands) { } } -fn setup(mut commands: Commands, mut rapier_config: ResMut) { +fn setup( + mut commands: Commands, + mut rapier_config: ResMut, + mut rip: ResMut, + p2p_session: Option>>, + synctest_session: Option>>, + spectator_session: Option>>, +) { rapier_config.gravity = Vec2::ZERO; let color = commands @@ -383,40 +452,50 @@ fn setup(mut commands: Commands, mut rapier_config: ResMut) }) .id(); - commands - .spawn() - .insert_bundle(SpriteBundle { - transform: Transform { - translation: Vec3::new(0.0, 0.0, 0.0), - scale: Vec3::splat(10.0), - ..default() - }, - sprite: Sprite { - color: Color::WHITE, + let num_players = p2p_session + .map(|s| s.num_players()) + .or_else(|| synctest_session.map(|s| s.num_players())) + .or_else(|| spectator_session.map(|s| s.num_players())) + .expect("No GGRS session found"); + + for handle in 0..num_players { + commands + .spawn() + .insert_bundle(SpriteBundle { + transform: Transform { + translation: Vec3::new(handle as f32, 0.0, 0.0), + scale: Vec3::splat(10.0), + ..default() + }, + sprite: Sprite { + color: Color::WHITE, + ..default() + }, ..default() - }, - ..default() - }) - .push_children(&[color]) - .insert(Player { - speed: 150.0, - radius: 10.0, - }) - .insert(RigidBody::Dynamic) - .insert(Restitution::coefficient(0.0)) - .insert(Collider::ball(1.0)) - .insert(LockedAxes::ROTATION_LOCKED) - .insert(Damping { - linear_damping: 30.0, - angular_damping: 1.0, - }) - .insert(Friction { - coefficient: 0.0, - combine_rule: CoefficientCombineRule::Min, - }) - .insert(Ccd::enabled()) - .insert(Velocity::zero()) - .insert(CollisionGroups::new(0b001, 0b111)); + }) + .push_children(&[color]) + .insert(Player { + handle, + speed: 150.0, + radius: 10.0, + }) + .insert(RigidBody::Dynamic) + .insert(Restitution::coefficient(0.0)) + .insert(Collider::ball(1.0)) + .insert(LockedAxes::ROTATION_LOCKED) + .insert(Damping { + linear_damping: 30.0, + angular_damping: 1.0, + }) + .insert(Friction { + coefficient: 0.0, + combine_rule: CoefficientCombineRule::Min, + }) + .insert(Ccd::enabled()) + .insert(Velocity::zero()) + .insert(CollisionGroups::new(0b001, 0b111)) + .insert(Rollback::new(rip.next_id())); + } setup_map(commands); } -- cgit v1.2.3-54-g00ecf