
📝 Rust Code
use nannou::prelude::*;
use rand::Rng;
const WIN_W: u32 = 800;
const WIN_H: u32 = 800;
const RADIUS: f32 = 200.0;
const NUM_SPIKE: usize = 20;
const MIN_LEN: f32 = 50.0;
const MAX_LEN: f32 = 120.0;
const START_THICK: f32 = 25.0;
const END_THICK: f32 = 0.1;
const START_ALPHA: f32 = 1.0;
const END_ALPHA: f32 = 0.1;
const SEGMENTS: usize = 12;
const STAR_POS: (f32, f32) = (0.0, 0.0);
fn main() {
nannou::app(model)
.update(update)
.size(WIN_W, WIN_H)
.view(view)
.run();
}
struct Model {
lengths: Vec<f32>,
star_pos: Point2,
}
fn model(app: &App) -> Model {
let _window = app
.new_window()
.title("Star Flares (fixed position)")
.view(view)
.build()
.unwrap();
let mut rng = rand::thread_rng();
let lengths = (0..NUM_SPIKE)
.map(|_| rng.gen_range(MIN_LEN..=MAX_LEN))
.collect();
Model {
lengths,
star_pos: pt2(STAR_POS.0, STAR_POS.1),
}
}
fn update(_app: &App, _model: &mut Model, _update: Update) {}
fn view(app: &App, model: &Model, frame: Frame) {
let draw = app.draw();
draw.background().color(hsla(0.0, 0.0, 0.0, 1.0));
let center = model.star_pos;
let white = hsla(0.0, 0.0, 1.0, 1.0);
draw.ellipse()
.no_fill()
.stroke(white)
.stroke_weight(1.0)
.x_y(center.x, center.y)
.w_h(RADIUS * 2.0, RADIUS * 2.0);
let tau = std::f32::consts::TAU;
for (i, &len) in model.lengths.iter().enumerate() {
let angle = (i as f32 / NUM_SPIKE as f32) * tau;
let dir = vec2(angle.cos(), angle.sin());
let perp = vec2(-dir.y, dir.x);
let base_center = center + dir * RADIUS;
for s in 0..SEGMENTS {
let t0 = s as f32 / SEGMENTS as f32;
let t1 = (s + 1) as f32 / SEGMENTS as f32;
let p0 = base_center + dir * (len * t0);
let p1 = base_center + dir * (len * t1);
let w0 = lerp(START_THICK, END_THICK, t0);
let w1 = lerp(START_THICK, END_THICK, t1);
let a0 = lerp(START_ALPHA, END_ALPHA, t0);
let a1 = lerp(START_ALPHA, END_ALPHA, t1);
let alpha = (a0 + a1) * 0.5;
let color = hsla(0.0, 0.0, 1.0, alpha);
let left0 = p0 + perp * (w0 * 0.5);
let right0 = p0 - perp * (w0 * 0.5);
let left1 = p1 + perp * (w1 * 0.5);
let right1 = p1 - perp * (w1 * 0.5);
draw.tri()
.points(pt2(left0.x, left0.y), pt2(right0.x, right0.y), pt2(left1.x, left1.y))
.color(color);
draw.tri()
.points(pt2(right0.x, right0.y), pt2(right1.x, right1.y), pt2(left1.x, left1.y))
.color(color);
}
let tip = base_center + dir * len;
let tip_color = hsla(0.0, 0.0, 1.0, END_ALPHA);
let tip_left = tip + perp * (END_THICK * 0.5);
let tip_right = tip - perp * (END_THICK * 0.5);
draw.tri()
.points(pt2(tip_left.x, tip_left.y), pt2(tip_right.x, tip_right.y), pt2(tip.x, tip.y))
.color(tip_color);
}
draw.to_frame(app, &frame).unwrap();
}
fn lerp(a: f32, b: f32, t: f32) -> f32 {
a + (b - a) * t
}