
📝 Rust Code
use nannou::prelude::*;
const NUM_BALLS: usize = 20;
const WINDOW_SIZE: f32 = 800.0;
const BALL_RADIUS: f32 = 10.0;
const GRAVITY: f32 = -0.1;
const FLOOR_Y: f32 = -390.0;
const WALL_X: f32 = 390.0;
const RESTITUTION: f32 = 0.7;
struct Ball {
position: Vec2,
velocity: Vec2,
}
struct Model {
balls: Vec<Ball>,
}
fn main() {
nannou::app(model).update(update).run();
}
fn model(app: &App) -> Model {
app.new_window()
.size(WINDOW_SIZE as u32, WINDOW_SIZE as u32)
.view(view)
.build()
.unwrap();
let balls = (0..NUM_BALLS)
.map(|_| Ball {
position: vec2(
random_range(-WINDOW_SIZE / 2.0, WINDOW_SIZE / 2.0),
random_range(200.0, 400.0)
),
velocity: vec2(
random_range(-2.0, 2.0),
random_range(-2.0, 2.0)
),
})
.collect();
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;
if ball.position.y < FLOOR_Y {
ball.position.y = FLOOR_Y;
ball.velocity.y *= -RESTITUTION;
}
if ball.position.x > WALL_X {
ball.position.x = WALL_X;
ball.velocity.x *= -1.0;
}
if ball.position.x < -WALL_X {
ball.position.x = -WALL_X;
ball.velocity.x *= -1.0;
}
}
}
fn view(app: &App, model: &Model, frame: Frame) {
let draw = app.draw();
let frame_nth = frame.nth();
if frame_nth == 0 {
draw.rect()
.w_h(800.0, 800.0)
.color(hsla(0.0, 0.0, 0.01, 1.0));
} else {
draw.rect()
.w_h(800.0, 800.0)
.color(hsla(0.0, 0.0, 0.01, 0.08));
}
for ball in &model.balls {
draw.ellipse()
.xy(ball.position)
.radius(BALL_RADIUS)
.color(rgba(0.0, 0.7, 0.8, 0.8));
}
draw.to_frame(app, &frame).unwrap();
}