:: BASIC_21_spikes_around_circle

BamgasiJM·2025년 10월 5일

Nannou <BASIC>

목록 보기
32/41
post-thumbnail

📝 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);
        }

        // 끝 tip
        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
}

profile
Coding Art with Blender / oF / Processing / p5.js / nannou

0개의 댓글