Compare commits
9 Commits
Author | SHA1 | Date |
---|---|---|
Zynh0722 | e259bf6019 | |
Zynh0722 | 4c36162aa5 | |
Zynh0722 | 8cde3ba399 | |
Zynh0722 | 1e90b2c514 | |
Zynh0722 | 5bba4f019e | |
Zynh0722 | b7a5277a11 | |
Zynh0722 | be7c6763f0 | |
Zynh0722 | 9d5ced0539 | |
Zynh0722 | 8d822448f8 |
109
src/main.rs
109
src/main.rs
|
@ -1,6 +1,5 @@
|
||||||
mod drawable;
|
mod drawable;
|
||||||
mod engine;
|
mod engine;
|
||||||
mod particle;
|
|
||||||
|
|
||||||
use drawable::DrawShape;
|
use drawable::DrawShape;
|
||||||
use engine::{PhysicsEngine, PhysicsState};
|
use engine::{PhysicsEngine, PhysicsState};
|
||||||
|
@ -8,33 +7,49 @@ use engine::{PhysicsEngine, PhysicsState};
|
||||||
use nalgebra::vector;
|
use nalgebra::vector;
|
||||||
use nannou::prelude::*;
|
use nannou::prelude::*;
|
||||||
use rapier2d::{
|
use rapier2d::{
|
||||||
dynamics::{RigidBodyBuilder, RigidBodySet},
|
dynamics::{RigidBodyBuilder, RigidBodyHandle, RigidBodySet},
|
||||||
geometry::{ColliderBuilder, ColliderSet},
|
geometry::{ColliderBuilder, ColliderSet},
|
||||||
};
|
};
|
||||||
|
|
||||||
const WINDOW_WIDTH: u32 = 512;
|
const WINDOW_WIDTH: u32 = 512;
|
||||||
const WINDOW_HEIGHT: u32 = WINDOW_WIDTH;
|
const WINDOW_HEIGHT: u32 = WINDOW_WIDTH;
|
||||||
const PARTICLE_COUNT: u32 = 200;
|
const PARTICLE_COUNT: u32 = 200;
|
||||||
const PARTICLE_SIZE: f32 = 10.0;
|
const PARTICLE_SIZE: f32 = 5.;
|
||||||
|
|
||||||
struct Model {
|
struct Model {
|
||||||
// Store the window ID so we can refer to this specific window later if needed.
|
// Store the window ID so we can refer to this specific window later if needed.
|
||||||
_window: WindowId,
|
window: WindowId,
|
||||||
// particles: Vec<Particle>,
|
// particles: Vec<Particle>,
|
||||||
engine: PhysicsEngine,
|
engine: PhysicsEngine,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fill_particles(_app: &App, colliders: &mut ColliderSet, bodies: &mut RigidBodySet) {
|
fn random_vec_in_rect(boundary: &Rect) -> nalgebra::Vector2<f32> {
|
||||||
let boundary = _app.window_rect();
|
|
||||||
for _ in 0..PARTICLE_COUNT {
|
|
||||||
let x = random_range(-100., 100.);
|
let x = random_range(-100., 100.);
|
||||||
let y = random_range(-150., boundary.top());
|
let y = random_range(-150., boundary.top());
|
||||||
|
|
||||||
|
vector![x, y]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fill_particles(boundary: &Rect, colliders: &mut ColliderSet, bodies: &mut RigidBodySet) {
|
||||||
|
// Keeping track of already placed balls to avoid overlap
|
||||||
|
// Need to look into a way to do this with rapier directly
|
||||||
|
let mut positions: Vec<nalgebra::Vector2<f32>> = Vec::new();
|
||||||
|
|
||||||
|
for _ in 0..PARTICLE_COUNT {
|
||||||
|
let mut xy = random_vec_in_rect(boundary);
|
||||||
|
while !positions
|
||||||
|
.iter()
|
||||||
|
.all(|pos| pos.metric_distance(&xy) > PARTICLE_SIZE * 2.)
|
||||||
|
{
|
||||||
|
xy = random_vec_in_rect(boundary)
|
||||||
|
}
|
||||||
|
positions.push(xy);
|
||||||
|
|
||||||
/* Create the bouncing ball. */
|
/* Create the bouncing ball. */
|
||||||
let rigid_body = RigidBodyBuilder::dynamic()
|
let rigid_body = RigidBodyBuilder::dynamic().translation(xy).build();
|
||||||
.translation(vector![x, y])
|
let collider = ColliderBuilder::ball(PARTICLE_SIZE)
|
||||||
|
.restitution(0.1)
|
||||||
.build();
|
.build();
|
||||||
let collider = ColliderBuilder::ball(5.).restitution(0.1).build();
|
|
||||||
let ball_body_handle = bodies.insert(rigid_body);
|
let ball_body_handle = bodies.insert(rigid_body);
|
||||||
colliders.insert_with_parent(collider, ball_body_handle, bodies);
|
colliders.insert_with_parent(collider, ball_body_handle, bodies);
|
||||||
}
|
}
|
||||||
|
@ -46,7 +61,7 @@ fn model(app: &App) -> Model {
|
||||||
// per app
|
// per app
|
||||||
|
|
||||||
// Create a new window! Store the ID so we can refer to it later.
|
// Create a new window! Store the ID so we can refer to it later.
|
||||||
let _window = app
|
let window = app
|
||||||
.new_window()
|
.new_window()
|
||||||
.size(WINDOW_WIDTH, WINDOW_HEIGHT)
|
.size(WINDOW_WIDTH, WINDOW_HEIGHT)
|
||||||
.title("nannou")
|
.title("nannou")
|
||||||
|
@ -57,43 +72,79 @@ fn model(app: &App) -> Model {
|
||||||
|
|
||||||
let mut engine = PhysicsEngine {
|
let mut engine = PhysicsEngine {
|
||||||
state: PhysicsState {
|
state: PhysicsState {
|
||||||
gravity: vector![0.0, -9.81 * 10.0],
|
gravity: vector![0., -9.81 * 10.],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let boundary = app.window(window).unwrap().rect();
|
||||||
|
|
||||||
/* Create the ground. */
|
/* Create the ground. */
|
||||||
let collider = ColliderBuilder::cuboid(100.0, 10.0)
|
let collider = ColliderBuilder::cuboid(boundary.w(), 4.)
|
||||||
.translation(vector![0.0, -200.0])
|
.translation(vector![0., boundary.bottom()])
|
||||||
.build();
|
.build();
|
||||||
engine.state.colliders.insert(collider);
|
engine.state.colliders.insert(collider);
|
||||||
|
|
||||||
// let mut particles = Vec::new();
|
/* Create the walls. */
|
||||||
|
let collider = ColliderBuilder::cuboid(4., boundary.h())
|
||||||
|
.translation(vector![boundary.left(), 0.])
|
||||||
|
.build();
|
||||||
|
engine.state.colliders.insert(collider);
|
||||||
|
let collider = ColliderBuilder::cuboid(4., boundary.h())
|
||||||
|
.translation(vector![boundary.right(), 0.])
|
||||||
|
.build();
|
||||||
|
engine.state.colliders.insert(collider);
|
||||||
|
|
||||||
// fill_particles(app, &mut particles);
|
/* Create the ceiling. */
|
||||||
fill_particles(app, &mut engine.state.colliders, &mut engine.state.bodies);
|
let collider = ColliderBuilder::cuboid(boundary.w(), 4.)
|
||||||
|
.translation(vector![0., boundary.top()])
|
||||||
|
.build();
|
||||||
|
engine.state.colliders.insert(collider);
|
||||||
|
|
||||||
Model {
|
fill_particles(
|
||||||
_window,
|
&boundary,
|
||||||
// particles,
|
&mut engine.state.colliders,
|
||||||
engine,
|
&mut engine.state.bodies,
|
||||||
}
|
);
|
||||||
|
|
||||||
|
Model { window, engine }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle events related to the window and update the model if necessary
|
// Handle events related to the window and update the model if necessary
|
||||||
fn event(app: &App, _model: &mut Model, event: WindowEvent) {
|
fn event(app: &App, model: &mut Model, event: WindowEvent) {
|
||||||
if let KeyReleased(Key::Escape) = event {
|
if let KeyReleased(Key::Escape) = event {
|
||||||
app.quit()
|
app.quit()
|
||||||
}
|
}
|
||||||
|
|
||||||
// if let Resized(_) = event {
|
if let Resized(_) = event {
|
||||||
// model.particles.clear();
|
// Rust borrowing rules means I need to first gather a list of handles,
|
||||||
//
|
// then delete them all
|
||||||
// fill_particles(app, &mut model.particles);
|
let handles: Vec<RigidBodyHandle> = model
|
||||||
// }
|
.engine
|
||||||
|
.state
|
||||||
|
.bodies
|
||||||
|
.iter()
|
||||||
|
.map(|(handle, _)| handle)
|
||||||
|
.collect();
|
||||||
|
|
||||||
// println!("{:?}", event);
|
for handle in handles {
|
||||||
|
model.engine.state.bodies.remove(
|
||||||
|
handle,
|
||||||
|
&mut model.engine.state.islands,
|
||||||
|
&mut model.engine.state.colliders,
|
||||||
|
&mut model.engine.state.joints,
|
||||||
|
&mut model.engine.state.multibody_joints,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fill_particles(
|
||||||
|
&app.window(model.window).unwrap().rect(),
|
||||||
|
&mut model.engine.state.colliders,
|
||||||
|
&mut model.engine.state.bodies,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the state of your application here. By default, this gets called right before `view`.
|
// Update the state of your application here. By default, this gets called right before `view`.
|
||||||
|
|
|
@ -1,43 +0,0 @@
|
||||||
use crate::drawable::Drawable;
|
|
||||||
use crate::PARTICLE_SIZE;
|
|
||||||
|
|
||||||
use nannou::prelude::*;
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct Particle {
|
|
||||||
pub pos: Vec2,
|
|
||||||
pub start_pos: Vec2,
|
|
||||||
pub radius: f32,
|
|
||||||
pub time_offset: f32,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Particle {
|
|
||||||
pub fn new(pos: Vec2) -> Self {
|
|
||||||
Self {
|
|
||||||
pos,
|
|
||||||
start_pos: pos,
|
|
||||||
..Default::default()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for Particle {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self {
|
|
||||||
pos: Default::default(),
|
|
||||||
radius: PARTICLE_SIZE,
|
|
||||||
start_pos: Default::default(),
|
|
||||||
time_offset: random_range(-PI, PI),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Drawable for Particle {
|
|
||||||
fn draw(&self, draw: &Draw) {
|
|
||||||
draw.ellipse()
|
|
||||||
.color(RED)
|
|
||||||
.stroke_weight(1.0)
|
|
||||||
.radius(self.radius)
|
|
||||||
.xy(self.pos);
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue