
đ Rust Code
use nannou::prelude::*;
fn main() {
nannou::app(model).update(update).run();
}
struct Ball {
position: Vec2,
velocity: Vec2,
}
struct Model {
balls: Vec<Ball>,
gravity: f32,
}
fn model(app: &App) -> Model {
app.new_window().size(800, 800).view(view).build().unwrap();
let balls = (0..5000)
.map(|_| Ball {
position: vec2(random_range(-400.0, 400.0), random_range(0.0, 800.0)),
velocity: vec2(0.0, random_range(-5.0, 5.0)),
})
.collect();
Model { balls, gravity: -0.1 }
}
fn update(_app: &App, model: &mut Model, _update: Update) {
for ball in &mut model.balls {
ball.velocity.y += model.gravity;
ball.position += ball.velocity;
if ball.position.y < -390.0 {
ball.position.y = -390.0;
ball.velocity.y *= -0.9;
}
if ball.position.x > 390.0 {
ball.position.x = 390.0;
ball.velocity.x *= -0.4;
}
if ball.position.x < -390.0 {
ball.position.x = -390.0;
ball.velocity.x *= -0.8;
}
}
}
fn view(app: &App, model: &Model, frame: Frame) {
let draw = app.draw();
draw.rect().w_h(800.0, 800.0).color(hsla(0.0, 0.0, 0.01, 0.1));
for ball in &model.balls {
draw.ellipse().xy(ball.position).radius(1.5).color(rgba(0.0, 1.0, 0.8, 0.8));
}
draw.to_frame(app, &frame).unwrap();
}
đ Rust Code + Refactoring
use nannou::prelude::*;
const NUM_BALLS: usize = 5000;
const WINDOW_SIZE: f32 = 800.0;
const BALL_RADIUS: f32 = 1.5;
const GRAVITY: f32 = -0.1;
const FLOOR_Y: f32 = -390.0;
const WALL_X: f32 = 390.0;
const BOUNCE_LOSS_Y: f32 = -0.9;
const BOUNCE_LOSS_X_RIGHT: f32 = -0.4;
const BOUNCE_LOSS_X_LEFT: f32 = -0.8;
fn main() {
nannou::app(model).update(update).run();
}
struct Ball {
position: Vec2,
velocity: Vec2,
}
struct Model {
balls: Vec<Ball>,
}
fn model(app: &App) -> Model {
app.new_window()
.size(WINDOW_SIZE as u32, WINDOW_SIZE as u32)
.view(view)
.build()
.unwrap();
let mut balls = Vec::with_capacity(NUM_BALLS);
for _ in 0..NUM_BALLS {
balls.push(Ball {
position: vec2(
random_range(-WINDOW_SIZE / 2.0, WINDOW_SIZE / 2.0),
random_range(0.0, WINDOW_SIZE),
),
velocity: vec2(0.0, random_range(-5.0, 5.0)),
});
}
Model { balls }
}
fn update(_app: &App, model: &mut Model, _update: Update) {
for ball in &mut model.balls {
ball.velocity.y += GRAVITY;
ball.position += ball.velocity;
handle_collision(ball);
}
}
fn handle_collision(ball: &mut Ball) {
if ball.position.y < FLOOR_Y {
ball.position.y = FLOOR_Y;
ball.velocity.y *= BOUNCE_LOSS_Y;
}
if ball.position.x > WALL_X {
ball.position.x = WALL_X;
ball.velocity.x *= BOUNCE_LOSS_X_RIGHT;
}
if ball.position.x < -WALL_X {
ball.position.x = -WALL_X;
ball.velocity.x *= BOUNCE_LOSS_X_LEFT;
}
}
fn view(app: &App, model: &Model, frame: Frame) {
let draw = app.draw();
draw.rect()
.w_h(WINDOW_SIZE, WINDOW_SIZE)
.color(hsla(0.0, 0.0, 0.01, 0.1));
for ball in &model.balls {
draw.ellipse()
.xy(ball.position)
.radius(BALL_RADIUS)
.color(rgba(0.0, 1.0, 0.8, 0.8));
}
draw.to_frame(app, &frame).unwrap();
}