Add command-line options with argh

This commit is contained in:
Tyler Hallada 2020-08-13 00:52:08 -04:00
parent 816b077eb9
commit 9d385a3cd4
4 changed files with 96 additions and 15 deletions

45
Cargo.lock generated
View File

@ -62,6 +62,35 @@ version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33954243bd79057c2de7338850b85983a44588021f8a5fee574a8888c6de4344" checksum = "33954243bd79057c2de7338850b85983a44588021f8a5fee574a8888c6de4344"
[[package]]
name = "argh"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca1877e24cecacd700d469066e0160c4f8497cc5635367163f50c8beec820154"
dependencies = [
"argh_derive",
"argh_shared",
]
[[package]]
name = "argh_derive"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e742194e0f43fc932bcb801708c2b279d3ec8f527e3acda05a6a9f342c5ef764"
dependencies = [
"argh_shared",
"heck",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "argh_shared"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e1ba68f4276a778591e36a0c348a269888f3a177c8d2054969389e3b59611ff5"
[[package]] [[package]]
name = "arrayvec" name = "arrayvec"
version = "0.5.1" version = "0.5.1"
@ -138,6 +167,7 @@ dependencies = [
name = "bevy-nbody" name = "bevy-nbody"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"argh",
"bevy", "bevy",
"bigbang", "bigbang",
"rand", "rand",
@ -1425,6 +1455,15 @@ dependencies = [
"autocfg", "autocfg",
] ]
[[package]]
name = "heck"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205"
dependencies = [
"unicode-segmentation",
]
[[package]] [[package]]
name = "hermit-abi" name = "hermit-abi"
version = "0.1.15" version = "0.1.15"
@ -2409,6 +2448,12 @@ version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0685c84d5d54d1c26f7d3eb96cd41550adb97baed141a761cf335d3d33bcd0ae" checksum = "0685c84d5d54d1c26f7d3eb96cd41550adb97baed141a761cf335d3d33bcd0ae"
[[package]]
name = "unicode-segmentation"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0"
[[package]] [[package]]
name = "unicode-xid" name = "unicode-xid"
version = "0.2.1" version = "0.2.1"

View File

@ -7,6 +7,7 @@ edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
argh = "0.1"
bevy = "0.1" bevy = "0.1"
bigbang = "0.0.9" bigbang = "0.0.9"
rand = "0.7" rand = "0.7"

View File

@ -4,6 +4,27 @@ An N-body simulation in Rust using the [bevy](https://bevyengine.org) crate for
![screenshot](assets/nbody.png) ![screenshot](assets/nbody.png)
## Install
Clone the repo, and run `cargo build --release`. The executable will be under `target/release/`.
## Usage
```
Usage: bevy-nbody [-n <num-bodies>] [-t <time-step>] [-w <width>] [-h <height>] [-s <scale>]
n-body simulation in bevy using bigbang
Options:
-n, --num-bodies number of bodies in the simulation
-t, --time-step granularity of simulation (how much each frame impacts
movement)
-w, --width initial width of spawned window
-h, --height initial height of spawned window
-s, --scale initial scale of view (bigger = more zoomed out)
--help display usage information
```
## Controls ## Controls
|key | control| |key | control|

View File

@ -1,3 +1,4 @@
use argh::FromArgs;
use bevy::{ use bevy::{
diagnostic::{FrameTimeDiagnosticsPlugin, PrintDiagnosticsPlugin}, diagnostic::{FrameTimeDiagnosticsPlugin, PrintDiagnosticsPlugin},
input::keyboard::{ElementState, KeyboardInput}, input::keyboard::{ElementState, KeyboardInput},
@ -10,6 +11,21 @@ use bevy::{
use bigbang::{Entity, GravTree}; use bigbang::{Entity, GravTree};
use rand::Rng; use rand::Rng;
#[derive(FromArgs)]
#[argh(description = "n-body simulation in bevy using bigbang")]
struct Options {
#[argh(option, default = "100", short = 'n', description = "number of bodies in the simulation")]
num_bodies: usize,
#[argh(option, default = "0.02", short = 't', description = "granularity of simulation (how much each frame impacts movement)")]
time_step: f64,
#[argh(option, default = "1280", short = 'w', description = "initial width of spawned window")]
width: u32,
#[argh(option, default = "720", short = 'h', description = "initial height of spawned window")]
height: u32,
#[argh(option, default = "10.0", short = 's', description = "initial scale of view (bigger = more zoomed out)")]
scale: f32
}
struct Simulation(GravTree<Entity>); struct Simulation(GravTree<Entity>);
#[derive(Default)] #[derive(Default)]
@ -24,19 +40,14 @@ struct State {
follow_body_index: Option<usize>, follow_body_index: Option<usize>,
} }
static INITIAL_WIDTH: u32 = 1280;
static INITIAL_HEIGHT: u32 = 720;
static INITIAL_SCALE: f32 = 10.;
static TIME_STEP: f64 = 0.02;
static NUM_BODIES: u32 = 100;
fn main() { fn main() {
let options: Options = argh::from_env();
App::build() App::build()
.add_resource(Msaa { samples: 4 }) .add_resource(Msaa { samples: 4 })
.add_resource(WindowDescriptor { .add_resource(WindowDescriptor {
title: "bevy-nbody".to_string(), title: "bevy-nbody".to_string(),
width: INITIAL_WIDTH, width: options.width,
height: INITIAL_HEIGHT, height: options.height,
..Default::default() ..Default::default()
}) })
.add_default_plugins() .add_default_plugins()
@ -45,9 +56,10 @@ fn main() {
.init_resource::<State>() .init_resource::<State>()
.add_resource(ClearColor(Color::rgb(0.01, 0.01, 0.01))) .add_resource(ClearColor(Color::rgb(0.01, 0.01, 0.01)))
.add_resource(Simulation(GravTree::new( .add_resource(Simulation(GravTree::new(
&initialize_bodies(INITIAL_WIDTH, INITIAL_HEIGHT, INITIAL_SCALE), &initialize_bodies(options.num_bodies, options.width, options.height, options.scale),
TIME_STEP, options.time_step,
))) )))
.add_resource(options)
.add_startup_system(add_bodies.system()) .add_startup_system(add_bodies.system())
.add_system(time_step.system()) .add_system(time_step.system())
.add_system(update_bodies.system()) .add_system(update_bodies.system())
@ -57,10 +69,10 @@ fn main() {
.run(); .run();
} }
fn initialize_bodies(width: u32, height: u32, scale: f32) -> Vec<Entity> { fn initialize_bodies(num: usize, width: u32, height: u32, scale: f32) -> Vec<Entity> {
let mut rng = rand::thread_rng(); let mut rng = rand::thread_rng();
let mut bodies = vec![]; let mut bodies = vec![];
for i in 0..NUM_BODIES { for i in 0..num {
let mass = if i == 0 { let mass = if i == 0 {
// big boi // big boi
rng.gen_range(500., 1500.) rng.gen_range(500., 1500.)
@ -93,11 +105,12 @@ fn add_bodies(
mut meshes: ResMut<Assets<Mesh>>, mut meshes: ResMut<Assets<Mesh>>,
asset_server: Res<AssetServer>, asset_server: Res<AssetServer>,
grav_tree: Res<Simulation>, grav_tree: Res<Simulation>,
options: Res<Options>,
) { ) {
let mut rng = rand::thread_rng(); let mut rng = rand::thread_rng();
let texture = asset_server.load("assets/circle.png").unwrap(); let texture = asset_server.load("assets/circle.png").unwrap();
commands.spawn(Camera2dComponents { commands.spawn(Camera2dComponents {
scale: Scale(INITIAL_SCALE), scale: Scale(options.scale),
..Camera2dComponents::default() ..Camera2dComponents::default()
}); });
@ -239,6 +252,7 @@ fn keyboard_input(
keyboard_input_events: Res<Events<KeyboardInput>>, keyboard_input_events: Res<Events<KeyboardInput>>,
mut grav_tree: ResMut<Simulation>, mut grav_tree: ResMut<Simulation>,
windows: Res<Windows>, windows: Res<Windows>,
options: Res<Options>,
mut query: Query<(&Camera, &Scale, &mut Translation)>, mut query: Query<(&Camera, &Scale, &mut Translation)>,
) { ) {
for event in state.keyboard_event_reader.iter(&keyboard_input_events) { for event in state.keyboard_event_reader.iter(&keyboard_input_events) {
@ -249,8 +263,8 @@ fn keyboard_input(
translation.0.set_x(0.); translation.0.set_x(0.);
translation.0.set_y(0.); translation.0.set_y(0.);
grav_tree.0 = GravTree::new( grav_tree.0 = GravTree::new(
&initialize_bodies(window.width, window.height, scale.0), &initialize_bodies(options.num_bodies, window.width, window.height, scale.0),
TIME_STEP, options.time_step,
); );
} }
} }