Code Sketch - Wobbler
Nannou source code:
use nannou::prelude::*;
fn main() {
nannou::app(model)
.update(update)
.run();
}
struct Model {
cols: u32,
rows: u32,
grid_size: u32,
padding: u32,
wobble_timer: i32,
wobbler: [i32; 2],
}
fn model(app: &App) -> Model {
// Create a new window! Store the ID so we can refer to it later.
let width = 200;
let height = 200;
let grid_size = 40;
let padding = 5;
let cols = width / grid_size;
let rows = height / grid_size;
app.new_window()
.size(width, height)
.view(view)
.build()
.unwrap();
Model {
cols,
rows,
grid_size,
padding,
wobble_timer: 0,
wobbler: [0, 0],
}
}
fn update(_app: &App, model: &mut Model, _update: Update) {
model.wobble_timer += 1;
if model.wobble_timer > 10 {
model.wobbler[0] = map_range(random_f32(), 0.0, 1.0, 1.0, (model.cols - 1) as f32).floor() as i32;
model.wobbler[1] = map_range(random_f32(), 0.0, 1.0, 1.0, (model.rows - 1) as f32).floor() as i32;
model.wobble_timer = 0;
}
}
fn view(app: &App, model: &Model, frame: Frame) {
let draw = app.draw();
let win = app.main_window();
let win_r = win.rect();
if frame.nth() == 0 {
draw.background().color(BLACK);
}
draw.rect()
.w_h(win_r.w(), win_r.h())
.color(rgba(0.0, 0.0, 0.0, 0.01));
let t1 = app.time * 2.0;
let t2 = app.time * 3.0;
for i in 1..model.rows - 1 {
for j in 1..model.cols - 1 {
if model.wobbler[0] == i as i32 && model.wobbler[1] == j as i32 {
let mut x = map_range(i as f32, 0.0, model.rows as f32, win_r.left(), win_r.right()) + model.grid_size as f32 / 2.0;
let mut y = map_range(j as f32, 0.0, model.rows as f32, win_r.left(), win_r.right()) + model.grid_size as f32 / 2.0;
y += t1.sin() * (t2.sin() * 10.0);
x += t1.cos() * (t2.cos() * 10.0);
draw.rect()
.x_y(x, y)
.w_h(model.grid_size as f32 - model.padding as f32 / 2.0, model.grid_size as f32 - model.padding as f32 / 2.0)
.stroke_weight(2.0)
.color(BLACK)
.stroke(hsl(clamp(t1.sin(), 0.6, 0.7), 1.0, 0.5));
}
}
}
// Write the result of our drawing to the window's frame.
draw.to_frame(app, &frame).unwrap();
if frame.nth() < 300 {
let file_path = captured_frame_path(app, &frame);
app.main_window().capture_frame(file_path);
}
}
fn captured_frame_path(app: &App, frame: &Frame) -> std::path::PathBuf {
app.project_path()
.expect("failed to locate `project_path`")
.join("frames")
.join(format!("{:04}", frame.nth()))
.with_extension("png")
}