Compare commits

..

No commits in common. "1461dd11ec2e17a84ddd0772d91c9c00ead7eeae" and "9ac45e924923548ef03076327a3093d934ad4489" have entirely different histories.

13 changed files with 75 additions and 155 deletions

View file

@ -18,11 +18,9 @@
"rust-analyzer.cargo.targetDir": true,
"cSpell.words": [
"Backquote",
"Cheatbook",
"codegen",
"despawn",
"Despawns",
"Iyes",
"lerp",
"PRNG",
"recip",

View file

@ -37,7 +37,10 @@ bevy = { version = "0.16.0", default-features = false, features = [
bevy_rand = { version = "0.11.0", features = ["wyrand", "std"] }
clap = { version = "4.5.32", features = ["derive"] }
crossbeam-channel = "0.5.15"
log = { version = "0.4.27", features = ["release_max_level_warn"] }
log = { version = "*", features = [
"max_level_debug",
"release_max_level_warn",
] }
rand = { version = "0.9.1", default-features = false, features = [
"std",
"thread_rng",

View file

@ -1,15 +0,0 @@
# Distributed Physics Test
Messing around with learning Rust, Bevy, and trying to remember my networking course from university.
My hope is that I can make some sort of basic decentralized P2P physics system, but we'll see if I get that far.
## Thanks
This is my first Bevy project, so some things are inspired by or taken from the [bevy_new_2d](https://github.com/TheBevyFlock/bevy_new_2d) example repo from "The Bevy Flock".
I've also found the [Unofficial Bevy Cheatbook](https://bevy-cheatbook.github.io/introduction.html) by Ida Iyes to be a great resource, and have used some of the snippets it provides.
## License
I've licensed this as AGPL3 as I like the idea of the GPL and this is networking software.
Both of the sources in my thanks section are licensed under 0-attribution models that let my freely use and relicense any code I take from them so there's no legal issue there, although I would like to reiterate my thanks in both cases.

View file

@ -7,7 +7,7 @@ use bevy::{
prelude::*,
};
use crate::game::state::AppState;
use crate::AppState;
pub(super) fn dev_tools(app: &mut App) {
app.add_plugins(FpsOverlayPlugin::default());

View file

@ -1,13 +1,5 @@
mod objects;
mod plugin;
mod rng;
mod runtime;
mod seed;
mod setup;
pub mod state;
#[allow(unused_imports)]
pub mod prelude {
pub use super::plugin::{DataSource, GamePlugin};
pub use super::seed::Seed;
}
pub mod runtime;
pub mod seed;
pub mod setup;

View file

@ -1,7 +1,7 @@
use avian2d::prelude::*;
use bevy::prelude::*;
use super::state::AppState;
use crate::AppState;
/// Basic implementation of a physics object
#[derive(Component, Default)]

View file

@ -1,91 +0,0 @@
use std::net::SocketAddr;
use avian2d::PhysicsPlugins;
use bevy::{input::common_conditions::input_pressed, prelude::*};
use crate::net::NetIOPlugin;
use super::{
runtime::{move_camera, move_player, quit, zoom_camera},
seed::Seed,
setup::{check_for_seed, setup_balls, setup_from_seed, setup_player, setup_ui, setup_walls},
state::AppState,
};
#[derive(Debug, Clone, Copy)]
pub enum DataSource {
Address(SocketAddr),
Seed(Seed),
None,
}
impl DataSource {
pub fn try_from_options(address: Option<SocketAddr>, seed: Option<Seed>) -> Option<Self> {
match (address, seed) {
(None, None) => Some(DataSource::None),
(None, Some(seed)) => Some(DataSource::Seed(seed)),
(Some(address), None) => Some(DataSource::Address(address)),
(Some(_), Some(_)) => None,
}
}
fn try_to_address(&self) -> Option<SocketAddr> {
match self {
DataSource::Address(address) => Some(*address),
_ => None,
}
}
}
pub struct GamePlugin {
source: DataSource,
port: u16,
}
impl GamePlugin {
pub fn new(source: DataSource, port: u16) -> Self {
Self { source, port }
}
}
impl Plugin for GamePlugin {
fn build(&self, app: &mut App) {
app.add_plugins((
NetIOPlugin::new(self.port, self.source.try_to_address()),
PhysicsPlugins::default().with_length_unit(50.0),
))
.init_state::<AppState>()
.add_systems(Startup, setup_ui)
.add_systems(
OnEnter(AppState::InGame),
(
setup_from_seed,
(setup_player, setup_balls, setup_walls).after(setup_from_seed),
),
)
.add_systems(
FixedUpdate,
check_for_seed.run_if(in_state(AppState::Loading)),
)
.add_systems(
Update,
(
((move_player, move_camera).chain(), zoom_camera)
.run_if(in_state(AppState::InGame)),
quit.run_if(input_pressed(KeyCode::KeyQ)),
),
);
match self.source {
DataSource::Address(peer) => {
info!("Will retrieve seed from peer => {peer}");
}
DataSource::Seed(seed) => {
app.insert_resource(seed);
}
DataSource::None => {
app.insert_resource(Seed::random());
}
};
}
}

View file

@ -7,7 +7,7 @@ use bevy::prelude::*;
use rand::random;
/// Value with which to initialize the PRNG
#[derive(Resource, Debug, Clone, Copy)]
#[derive(Resource, Clone, Copy)]
pub struct Seed(u64);
impl Seed {

View file

@ -11,7 +11,7 @@ use bevy::{
use rand::{Rng as _, SeedableRng};
use wyrand::WyRand;
use super::state::AppState;
use crate::AppState;
use super::{
objects::{Ball, Player, Radius, Wall},

View file

@ -1,9 +0,0 @@
use bevy::prelude::*;
#[derive(States, Default, Debug, Clone, PartialEq, Eq, Hash)]
#[states(scoped_entities)]
pub enum AppState {
#[default]
Loading,
InGame,
}

View file

@ -1,15 +1,20 @@
use std::net::SocketAddr;
use avian2d::{math::Vector, prelude::*};
use bevy::prelude::*;
use bevy::{input::common_conditions::input_pressed, prelude::*};
use clap::{Args, Parser};
#[cfg(feature = "dev")]
mod dev;
mod game;
mod net;
use game::prelude::*;
mod game;
use game::{
runtime::{move_camera, move_player, quit, zoom_camera},
seed::Seed,
setup::{check_for_seed, setup_balls, setup_from_seed, setup_player, setup_ui, setup_walls},
};
mod net;
/// The initial configuration passed to the game's setup functions.
/// Also functions as a Bevy plugin to pass the configuration into the app.
@ -36,24 +41,60 @@ struct Source {
connect: Option<SocketAddr>,
}
#[derive(States, Default, Debug, Clone, PartialEq, Eq, Hash)]
#[states(scoped_entities)]
enum AppState {
#[default]
Loading,
InGame,
}
impl Plugin for AppSettings {
fn build(&self, app: &mut App) {
app.insert_resource(Gravity(Vector::ZERO)).add_plugins((
DefaultPlugins.set(WindowPlugin {
primary_window: Window {
title: "Distributed physics test".into(),
fit_canvas_to_parent: true,
app.insert_resource(Gravity(Vector::ZERO))
.add_plugins((
DefaultPlugins.set(WindowPlugin {
primary_window: Window {
title: "Distributed physics test".into(),
fit_canvas_to_parent: true,
..default()
}
.into(),
..default()
}
.into(),
..default()
}),
#[cfg(feature = "dev")]
dev::dev_tools,
GamePlugin::new(
DataSource::try_from_options(self.source.connect, self.source.seed).unwrap(),
self.port,
),
));
}),
PhysicsPlugins::default().with_length_unit(50.0),
#[cfg(feature = "dev")]
dev::dev_tools,
net::NetIOPlugin::new(self.port, self.source.connect),
))
.init_state::<AppState>()
.add_systems(Startup, setup_ui)
.add_systems(
OnEnter(AppState::InGame),
(
setup_from_seed,
(setup_player, setup_balls, setup_walls).after(setup_from_seed),
),
)
.add_systems(
FixedUpdate,
check_for_seed.run_if(in_state(AppState::Loading)),
)
.add_systems(
Update,
(
((move_player, move_camera).chain(), zoom_camera)
.run_if(in_state(AppState::InGame)),
quit.run_if(input_pressed(KeyCode::KeyQ)),
),
);
if let Some(ref seed) = self.source.seed {
app.insert_resource(*seed);
} else if let Some(ref peer) = self.source.connect {
info!("Will retrieve seed from peer => {peer}");
} else {
app.insert_resource(Seed::random());
}
}
}

View file

@ -1,5 +1,6 @@
mod plugin;
pub use plugin::NetIOPlugin;
mod socket;
mod thread;
mod types;
pub use plugin::NetIOPlugin;

View file

@ -2,7 +2,7 @@ use std::net::SocketAddr;
use bevy::prelude::*;
use crate::game::prelude::Seed;
use crate::game::seed::Seed;
use super::{
socket::bind_socket,