subtitled #16: ink spillage

main
annieversary 2021-09-08 18:36:37 +02:00
parent 7cf5891323
commit 5f8b643263
4 changed files with 127 additions and 0 deletions

8
Cargo.lock generated
View File

@ -2414,6 +2414,14 @@ dependencies = [
"utils", "utils",
] ]
[[package]]
name = "subtitled16"
version = "0.1.0"
dependencies = [
"nannou",
"utils",
]
[[package]] [[package]]
name = "subtitled2" name = "subtitled2"
version = "0.1.0" version = "0.1.0"

View File

@ -0,0 +1,8 @@
[package]
name = "subtitled16"
version = "0.1.0"
edition = "2018"
[dependencies]
nannou = "0.17"
utils = { path = "../utils" }

View File

@ -0,0 +1,108 @@
use std::time::Duration;
use nannou::prelude::*;
const R: f32 = 2.0;
fn main() {
nannou::app(model).update(update).simple_window(view).run();
}
#[derive(Clone)]
struct Point {
pos: IVec2,
color: f32,
}
impl Point {
fn new(pos: IVec2, color: f32) -> Self {
Self { pos, color }
}
}
fn neighbors(point: IVec2) -> Vec<IVec2> {
let mut cube = vec![];
let p = [-1, 0, 1];
for &x in &p {
for &y in &p {
if (x, y) != (0, 0) {
cube.push(ivec2(x, y) + point);
}
}
}
cube
}
struct Model {
points: Vec<Point>,
visits: Vec<Point>,
}
fn model(_app: &App) -> Model {
Model {
visits: vec![Point::new(IVec2::ZERO, random_range(0.0, 360.0))],
points: vec![],
}
}
fn update(app: &App, model: &mut Model, _update: Update) {
for _ in 0..20 {
run(app, model)
}
}
fn run(app: &App, model: &mut Model) {
let _t = app.elapsed_frames() as f32 / 60.0;
// take a random out of the visits list
let point = model.visits.remove(random_range(0, model.visits.len()));
// visit it and all it's neighbors
let neighbors = neighbors(point.pos)
.into_iter()
.filter(|p| {
model.visits.iter().find(|point| point.pos == *p).is_none()
&& model.points.iter().find(|point| point.pos == *p).is_none()
})
.collect::<Vec<_>>();
for n in neighbors {
model
.visits
// NOTE: this is where the randomization of the color happens
.push(Point::new(n, point.color + random_range(-10.0, 10.0)))
}
// move it to visited points
model.points.push(point);
}
fn view(app: &App, model: &Model, frame: Frame) {
let _t = frame.nth() as f32 / 60.0;
let draw = app.draw();
draw.background().color(SNOW);
for walker in &model.visits {
let h = walker.color / 360.0;
draw.ellipse()
.xy(walker.pos.as_f32() * R * 2.0)
.radius(R)
.color(hsl(h.fract(), 0.5, 0.7));
}
for walker in &model.points {
let h = walker.color / 360.0;
let p = walker.pos.as_f32() * R;
draw.quad()
.points(
p + R * vec2(1., 1.),
p + R * vec2(1., -1.),
p + R * vec2(-1., -1.),
p + R * vec2(-1., 1.),
)
.xy(p)
.color(hsl(h.fract(), 0.5, 0.5));
}
// cause otherwise it goes too fast when recording and it can't save the frames in time lmao
std::thread::sleep(Duration::from_millis(5));
draw.to_frame(app, &frame).unwrap();
utils::record::record(app, &frame);
}

View File

@ -46,3 +46,6 @@ impl Tup2Extension for (f32, f32) {
pub fn vec2_range(min: f32, max: f32) -> Vec2 { pub fn vec2_range(min: f32, max: f32) -> Vec2 {
vec2(random_range(min, max), random_range(min, max)) vec2(random_range(min, max), random_range(min, max))
} }
pub fn ivec2_range(min: i32, max: i32) -> IVec2 {
ivec2(random_range(min, max), random_range(min, max))
}