
๐ Rust Code
use nannou::noise::{NoiseFn, Perlin};
use nannou::prelude::*;
struct Particle {
position: Vec2,
history: Vec<Vec2>,
}
struct Model {
particles: Vec<Particle>,
perlin: Perlin,
}
fn main() {
nannou::app(model).update(update).run();
}
fn model(app: &App) -> Model {
app.new_window()
.size(800, 800)
.view(view)
.build()
.unwrap();
let mut particles = Vec::new();
let perlin = Perlin::new();
for _ in 0..2000 {
let x = random_range(-400.0, 400.0);
let y = random_range(-400.0, 400.0);
particles.push(Particle {
position: vec2(x, y),
history: Vec::new(),
});
}
Model { particles, perlin }
}
fn update(app: &App, model: &mut Model, _update: Update) {
let time = app.elapsed_frames() as f64 * 0.01;
for particle in model.particles.iter_mut() {
let noise_val = model
.perlin
.get([particle.position.x as f64 * 0.02, particle.position.y as f64 * 0.02, time]);
let angle = map_range(noise_val, -1.0, 1.0, 0.0, TAU);
let direction = vec2(angle.cos(), angle.sin());
let step = 5.0;
particle.position += direction * step;
particle.history.push(particle.position);
if particle.history.len() > 50 {
particle.history.remove(0);
}
}
}
fn view(app: &App, model: &Model, frame: Frame) {
let draw = app.draw();
draw.rect()
.wh(app.window_rect().wh())
.color(srgba(0.0, 0.0, 0.0, 0.05));
for particle in &model.particles {
if particle.history.len() > 1 {
draw.polyline()
.weight(0.5)
.points(particle.history.clone())
.color(WHITE);
}
}
draw.to_frame(app, &frame).unwrap();
}