Make RNG seedable

This commit is contained in:
Michael Bradley 2025-03-23 22:32:57 -04:00
parent 6732f5575c
commit 946e961633
Signed by: MichaelBradley
SSH key fingerprint: SHA256:cj/YZ5VT+QOKncqSkx+ibKTIn0Obg7OIzwzl9BL8EO8
5 changed files with 57 additions and 14 deletions

1
Cargo.lock generated
View file

@ -1607,6 +1607,7 @@ dependencies = [
"bevy", "bevy",
"log", "log",
"rand 0.9.0", "rand 0.9.0",
"rand_chacha 0.9.0",
] ]
[[package]] [[package]]

View file

@ -34,3 +34,4 @@ log = { version = "*", features = [
"release_max_level_warn", "release_max_level_warn",
] } ] }
rand = "0.9.0" rand = "0.9.0"
rand_chacha = "0.9.0"

2
src/lib.rs Normal file
View file

@ -0,0 +1,2 @@
mod random;
pub use random::Random;

View file

@ -9,18 +9,26 @@ use bevy::{
input::common_conditions::input_pressed, input::common_conditions::input_pressed,
prelude::*, prelude::*,
}; };
use rand::Rng;
use distributed_physics_test::Random;
const AREA_WIDTH: f32 = 750.; const AREA_WIDTH: f32 = 750.;
const PLAYER_SIZE: f32 = 30.; const PLAYER_SIZE: f32 = 30.;
fn main() { #[derive(Default)]
struct AppSettings {
seed: String,
}
fn main() -> AppExit {
run_app(AppSettings::default())
}
fn run_app(settings: AppSettings) -> AppExit {
App::new() App::new()
.add_plugins(( .add_plugins((
DefaultPlugins, DefaultPlugins,
PhysicsPlugins::default() PhysicsPlugins::default().with_length_unit(50.0),
.with_length_unit(50.0)
.set(PhysicsInterpolationPlugin::interpolate_all()),
)) ))
.add_systems( .add_systems(
Startup, Startup,
@ -31,11 +39,12 @@ fn main() {
(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))
.run(); .insert_resource(Random::seed(&settings.seed))
.run()
} }
fn setup_scene(mut commands: Commands) { fn setup_scene(mut commands: Commands) {
commands.spawn(Camera2d); commands.spawn((Name::new("Camera"), Camera2d, IsDefaultUiCamera));
} }
#[derive(Component, Default)] #[derive(Component, Default)]
@ -50,19 +59,16 @@ fn setup_balls(
mut commands: Commands, mut commands: Commands,
mut materials: ResMut<Assets<ColorMaterial>>, mut materials: ResMut<Assets<ColorMaterial>>,
mut meshes: ResMut<Assets<Mesh>>, mut meshes: ResMut<Assets<Mesh>>,
mut rng: ResMut<Random>,
) { ) {
let mut rng = rand::rng();
for _ in 0..20 { for _ in 0..20 {
let circle = Circle::new(rng.random_range(10.0..(PLAYER_SIZE - 5.))); let circle = Circle::new(rng.range(10.0..(PLAYER_SIZE - 5.)));
let mut transform = Transform::from_xyz( let mut transform = Transform::from_xyz(
0., 0.,
rng.random_range((PLAYER_SIZE + 5.)..(AREA_WIDTH / 2. - PLAYER_SIZE)), rng.range((PLAYER_SIZE + 5.)..(AREA_WIDTH / 2. - PLAYER_SIZE)),
0., 0.,
); );
transform.rotate_around( transform.rotate_around(Vec3::ZERO, Quat::from_rotation_z(rng.range(0.0..(PI * 2.))));
Vec3::ZERO,
Quat::from_rotation_z(rng.random_range(0.0..(PI * 2.))),
);
commands.spawn(( commands.spawn((
Ball, Ball,
Collider::from(circle), Collider::from(circle),

33
src/random.rs Normal file
View file

@ -0,0 +1,33 @@
use std::hash::{DefaultHasher, Hash, Hasher};
use bevy::prelude::*;
use rand::{
Rng, SeedableRng,
distr::uniform::{SampleRange, SampleUniform},
};
use rand_chacha::ChaCha8Rng;
#[derive(Resource)]
pub struct Random(ChaCha8Rng);
impl Random {
pub fn seed(seed: &String) -> Self {
Random(ChaCha8Rng::seed_from_u64(
seed.parse::<u64>().unwrap_or_else(|_| hash_string(seed)),
))
}
pub fn range<T, R>(&mut self, range: R) -> T
where
T: SampleUniform,
R: SampleRange<T>,
{
self.0.random_range(range)
}
}
fn hash_string(string: &String) -> u64 {
let mut state = DefaultHasher::new();
string.hash(&mut state);
state.finish()
}