Compare commits

..

2 commits

Author SHA1 Message Date
8e340b62b9
Temporarily disable nightly
All checks were successful
CI / Formatting (push) Successful in 1m6s
Was causing undefined symbol errors
2025-05-17 15:58:47 -04:00
b5792648eb
Update to Bevy 0.16
Also update RNG handling
2025-05-17 15:57:35 -04:00
6 changed files with 852 additions and 558 deletions

View file

@ -1,3 +1,3 @@
[target.x86_64-unknown-linux-gnu] [target.x86_64-unknown-linux-gnu]
linker = "clang" linker = "clang"
rustflags = ["-C", "link-arg=-fuse-ld=/usr/bin/mold", "-Zshare-generics=y"] rustflags = ["-C", "link-arg=-fuse-ld=/usr/bin/mold"] #, "-Zshare-generics=y"]

View file

@ -6,11 +6,14 @@
"rust-analyzer.check.command": "clippy", // "check", // "rust-analyzer.check.command": "clippy", // "check", //
"rust-analyzer.cargo.targetDir": true, "rust-analyzer.cargo.targetDir": true,
"cSpell.words": [ "cSpell.words": [
"codegen",
"despawn", "despawn",
"Despawns", "Despawns",
"recip", "recip",
"respawns", "respawns",
"timestep", "timestep",
"timesteps" "timesteps",
"winit",
"wyrand"
] ]
} }

1317
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -18,8 +18,8 @@ incremental = false
debug = false debug = false
[dependencies] [dependencies]
avian2d = { version = "0.2.1", features = ["serialize", "simd"] } avian2d = { version = "0.3.0", features = ["serialize", "simd"] }
bevy = { version = "0.15.3", default-features = false, features = [ bevy = { version = "0.16.0", default-features = false, features = [
"bevy_color", "bevy_color",
"bevy_core_pipeline", "bevy_core_pipeline",
"bevy_render", "bevy_render",
@ -28,12 +28,14 @@ bevy = { version = "0.15.3", default-features = false, features = [
"bevy_winit", "bevy_winit",
"dynamic_linking", "dynamic_linking",
"multi_threaded", "multi_threaded",
"std",
"wayland", "wayland",
] } ] }
bevy_rand = { version = "0.11.0", features = ["wyrand", "std"] }
clap = { version = "4.5.32", features = ["derive"] } clap = { version = "4.5.32", features = ["derive"] }
log = { version = "*", features = [ log = { version = "*", features = [
"max_level_debug", "max_level_debug",
"release_max_level_warn", "release_max_level_warn",
] } ] }
rand = "0.9.0" rand = { version = "0.9.1", default-features = false, features = ["std"] }
rand_chacha = "0.9.0" wyrand = "0.3.2"

View file

@ -1,2 +1,2 @@
[toolchain] [toolchain]
channel = "nightly" channel = "stable" # "nightly"

View file

@ -13,9 +13,10 @@ use bevy::{
input::common_conditions::input_pressed, input::common_conditions::input_pressed,
prelude::*, prelude::*,
}; };
use bevy_rand::prelude::{EntropyPlugin, GlobalEntropy, WyRand};
use clap::Parser; use clap::Parser;
use rand::{Rng, SeedableRng, rng}; use rand::Rng;
use rand_chacha::ChaCha8Rng; use wyrand::WyRand as LocalRng;
#[derive(Parser)] #[derive(Parser)]
#[command(version, about)] #[command(version, about)]
@ -28,15 +29,22 @@ fn main() -> AppExit {
run_app(AppSettings::parse()) run_app(AppSettings::parse())
} }
fn hash_string(string: &String) -> u64 {
let mut state = DefaultHasher::new();
string.hash(&mut state);
state.finish()
}
const BALL_SIZES: Range<f32> = 10.0..25.0; const BALL_SIZES: Range<f32> = 10.0..25.0;
const DIMENSION_SIZES: Range<f32> = 250.0..1000.0; const DIMENSION_SIZES: Range<f32> = 250.0..1000.0;
#[derive(Clone, Resource)]
struct Seed(u64);
impl From<String> for Seed {
fn from(value: String) -> Self {
Self(value.parse::<u64>().unwrap_or_else(|_| {
let mut state = DefaultHasher::new();
value.hash(&mut state);
state.finish()
}))
}
}
#[derive(Resource)] #[derive(Resource)]
struct PlayableArea(f32, f32); struct PlayableArea(f32, f32);
@ -44,13 +52,7 @@ struct PlayableArea(f32, f32);
struct PlayerSize(f32); struct PlayerSize(f32);
fn run_app(settings: AppSettings) -> AppExit { fn run_app(settings: AppSettings) -> AppExit {
let mut rng = ChaCha8Rng::seed_from_u64( let seed = Seed::from(settings.seed);
settings
.seed
.parse::<u64>()
.unwrap_or_else(|_| hash_string(&settings.seed)),
);
App::new() App::new()
.add_plugins(( .add_plugins((
DefaultPlugins.set(WindowPlugin { DefaultPlugins.set(WindowPlugin {
@ -63,18 +65,22 @@ fn run_app(settings: AppSettings) -> AppExit {
..default() ..default()
}), }),
PhysicsPlugins::default().with_length_unit(50.0), PhysicsPlugins::default().with_length_unit(50.0),
EntropyPlugin::<WyRand>::with_seed(seed.0.to_le_bytes()), // TODO: Tried to make and Into<[u8; 8]> for this but it wants to consume the value
)) ))
.add_systems(Startup, (setup_balls, setup_ui, setup_player, setup_walls)) .add_systems(
Startup,
(
setup_ui,
setup_pseudo_random,
(setup_player, setup_walls, setup_balls).after(setup_pseudo_random),
),
)
.add_systems( .add_systems(
Update, Update,
(move_player, quit.run_if(input_pressed(KeyCode::KeyQ))), (move_player, quit.run_if(input_pressed(KeyCode::KeyQ))),
) )
.insert_resource(Gravity(Vector::ZERO)) .insert_resource(Gravity(Vector::ZERO))
.insert_resource(PlayerSize(rng.random_range(BALL_SIZES))) .insert_resource(seed)
.insert_resource(PlayableArea(
rng.random_range(DIMENSION_SIZES),
rng.random_range(DIMENSION_SIZES),
))
.run() .run()
} }
@ -83,11 +89,11 @@ fn setup_ui(mut commands: Commands) {
} }
#[derive(Component, Default)] #[derive(Component, Default)]
#[require(Collider, Mesh2d, MeshMaterial2d<ColorMaterial>, Restitution(|| Restitution::new(1.0)), RigidBody, TransformInterpolation, Transform)] #[require(Collider, Mesh2d, MeshMaterial2d<ColorMaterial>, Restitution = Restitution::new(1.0), RigidBody, TransformInterpolation, Transform)]
struct GameObject; struct GameObject;
#[derive(Component, Default)] #[derive(Component, Default)]
#[require(GameObject, RigidBody(|| RigidBody::Dynamic))] #[require(GameObject, RigidBody = RigidBody::Dynamic)]
struct Ball; struct Ball;
fn setup_balls( fn setup_balls(
@ -96,7 +102,7 @@ fn setup_balls(
mut meshes: ResMut<Assets<Mesh>>, mut meshes: ResMut<Assets<Mesh>>,
region: Res<PlayableArea>, region: Res<PlayableArea>,
) { ) {
let mut random = rng(); let mut random = LocalRng::new(Default::default());
for _ in 0..50 { for _ in 0..50 {
let circle = Circle::new(random.random_range(BALL_SIZES)); let circle = Circle::new(random.random_range(BALL_SIZES));
commands.spawn(( commands.spawn((
@ -118,7 +124,7 @@ fn setup_balls(
} }
#[derive(Component, Default)] #[derive(Component, Default)]
#[require(Ball, RigidBody(|| RigidBody::Dynamic))] #[require(Ball)]
struct Player; struct Player;
fn setup_player( fn setup_player(
@ -136,8 +142,16 @@ fn setup_player(
)); ));
} }
fn setup_pseudo_random(mut commands: Commands, mut rng: GlobalEntropy<WyRand>) {
commands.insert_resource(PlayerSize(rng.random_range(BALL_SIZES)));
commands.insert_resource(PlayableArea(
rng.random_range(DIMENSION_SIZES),
rng.random_range(DIMENSION_SIZES),
));
}
#[derive(Component, Default)] #[derive(Component, Default)]
#[require(GameObject, RigidBody(|| RigidBody::Static))] #[require(GameObject, RigidBody = RigidBody::Static)]
struct Wall; struct Wall;
fn setup_walls( fn setup_walls(
@ -175,10 +189,10 @@ fn move_player(
time: Res<Time>, time: Res<Time>,
keyboard_input: Res<ButtonInput<KeyCode>>, keyboard_input: Res<ButtonInput<KeyCode>>,
mut player: Query<&mut LinearVelocity, With<Player>>, mut player: Query<&mut LinearVelocity, With<Player>>,
) { ) -> Result {
let acceleration = 500.0; let acceleration = 500.0;
let mut velocity = player.single_mut(); let mut velocity = player.single_mut()?;
let delta_time = time.delta_secs(); let delta_time = time.delta_secs();
if keyboard_input.any_pressed([KeyCode::KeyW, KeyCode::ArrowUp]) { if keyboard_input.any_pressed([KeyCode::KeyW, KeyCode::ArrowUp]) {
@ -193,8 +207,10 @@ fn move_player(
if keyboard_input.any_pressed([KeyCode::KeyD, KeyCode::ArrowRight]) { if keyboard_input.any_pressed([KeyCode::KeyD, KeyCode::ArrowRight]) {
velocity.x += acceleration * delta_time; velocity.x += acceleration * delta_time;
} }
Ok(())
} }
fn quit(mut exit: EventWriter<AppExit>) { fn quit(mut exit: EventWriter<AppExit>) {
exit.send(AppExit::Success); exit.write(AppExit::Success);
} }