:: BASIC_04_color_sqaure_rotation

BamgasiJM·2025년 9월 19일

Nannou <BASIC>

목록 보기
17/41
post-thumbnail

📝 Rust Code

use nannou::prelude::*;

fn main() {
    nannou::app(model).update(update).run();
}

struct Model {
    colors: Vec<Rgba>,
    rotation: f32,
}

fn model(app: &App) -> Model {
    app.new_window().view(view).build().unwrap();

    Model {
        colors: vec![
            rgba(1.0, 0.0, 0.0, 0.5), // 빨강
            rgba(0.0, 1.0, 0.0, 0.5), // 초록
            rgba(0.0, 0.0, 1.0, 0.5) // 파랑
        ],
        rotation: 0.0,
    }
}

fn update(_app: &App, model: &mut Model, _update: Update) {
    model.rotation += 0.01;
}

fn view(app: &App, model: &Model, frame: Frame) {
    let draw = app.draw();
    draw.background().color(rgba(0.0, 0.0, 0.0, 1.0));

    // 여러 도형 그리기
    for (i, &color) in model.colors.iter().enumerate() {
        let angle = model.rotation + ((i as f32) * TAU) / 3.0;
        let x = angle.cos() * 100.0;
        let y = angle.sin() * 100.0;

        draw.rect().xy(pt2(x, y)).wh(vec2(80.0, 80.0)).color(color).rotate(model.rotation);
    }

    draw.to_frame(app, &frame).unwrap();
}

📝 Rust Code + Comment

// Nannou 라이브러리의 주요 기능을 사용하기 위해 prelude 모듈을 가져옵니다.
// 이 모듈은 자주 사용되는 타입과 함수들을 자동으로 import 해줍니다.
use nannou::prelude::*;

// 프로그램의 진입점입니다.
// Nannou 애플리케이션을 생성하고 실행합니다.
fn main() {
    // nannou::app() 함수는 애플리케이션 빌더를 반환합니다.
    // - model: 애플리케이션 시작 시 초기 상태를 설정하는 함수
    // - update: 매 프레임마다 상태를 업데이트하는 함수
    // - run(): 실제로 창을 열고 렌더링 루프를 시작합니다.
    nannou::app(model).update(update).run();
}

// 애플리케이션의 상태를 저장하는 구조체입니다.
// 이 구조체는 프로그램 전체에서 유지되는 데이터를 담당합니다.
struct Model {
    // 세 가지 반투명 색상을 저장하는 벡터입니다.
    // Rgba는 Nannou에서 제공하는 색상 타입으로, (빨강, 초록, 파랑, 투명도)로 구성됩니다.
    colors: Vec<Rgba>,
    
    // 도형의 회전 각도를 저장하는 변수입니다.
    // f32 타입으로, 매 프레임마다 조금씩 증가하면서 회전 애니메이션을 구현합니다.
    rotation: f32,
}

// 애플리케이션이 시작될 때 한 번만 호출되는 함수입니다.
// 초기 상태(Model)를 반환합니다.
fn model(app: &App) -> Model {
    // 새로운 창을 생성하고, view 함수를 렌더링 콜백으로 설정합니다.
    // build()는 창 생성을 완료하고, unwrap()은 오류가 발생하면 프로그램을 중단시킵니다.
    app.new_window().view(view).build().unwrap();

    // 초기 Model 인스턴스를 반환합니다.
    Model {
        // 세 가지 색상을 반투명(알파 = 0.5)으로 설정합니다.
        // 각 색상은 Rgba 타입이며, 값은 0.0 ~ 1.0 사이입니다.
        colors: vec![
            rgba(1.0, 0.0, 0.0, 0.5), // 빨간색 (Red)
            rgba(0.0, 1.0, 0.0, 0.5), // 초록색 (Green)
            rgba(0.0, 0.0, 1.0, 0.5)  // 파란색 (Blue)
        ],
        // 초기 회전 각도는 0.0 라디안입니다.
        rotation: 0.0,
    }
}

// 매 프레임마다 호출되는 함수로, 애플리케이션의 상태를 업데이트합니다.
// - _app: 애플리케이션 객체 (여기서는 사용되지 않아서 _로 시작)
// - model: 가변 참조로, 상태를 수정할 수 있음
// - _update: 업데이트 이벤트 정보 (여기서는 사용되지 않음)
fn update(_app: &App, model: &mut Model, _update: Update) {
    // 매 프레임마다 회전 각도를 0.01 라디안씩 증가시킵니다.
    // 이 값이 커질수록 회전 속도가 빨라집니다.
    model.rotation += 0.01;
}

// 매 프레임마다 화면을 그리는 함수입니다.
// - app: 애플리케이션 객체
// - model: 현재 상태 (읽기 전용)
// - frame: 현재 프레임 버퍼 (렌더링 결과를 여기에 그립니다)
fn view(app: &App, model: &Model, frame: Frame) {
    // 그리기 명령을 담을 Draw 객체를 생성합니다.
    let draw = app.draw();

    // 배경을 검은색(완전 불투명)으로 설정합니다.
    draw.background().color(rgba(0.0, 0.0, 0.0, 1.0));

    // colors 벡터에 저장된 각 색상에 대해 도형을 그립니다.
    // enumerate()로 인덱스(i)와 색상(color)을 동시에 얻습니다.
    for (i, &color) in model.colors.iter().enumerate() {
        // 각 도형의 중심 위치를 원형으로 배치하기 위한 각도 계산
        // - model.rotation: 전체 회전 애니메이션 적용
        // - (i as f32) * TAU / 3.0: 3개의 도형을 원 위에 균등하게 배치
        //   (TAU = 2π, 즉 360도)
        let angle = model.rotation + ((i as f32) * TAU) / 3.0;

        // 삼각함수를 사용해 원형 경로 상의 (x, y) 좌표 계산
        // 반지름은 100.0 픽셀
        let x = angle.cos() * 100.0;
        let y = angle.sin() * 100.0;

        // 사각형(rectangle)을 그립니다:
        // - xy(pt2(x, y)): 사각형 중심 좌표 설정 (pt2는 2D 점 생성)
        // - wh(vec2(80.0, 80.0)): 너비(width)와 높이(height)를 80x80으로 설정
        // - color(color): 현재 반복에서의 색상 적용
        // - rotate(model.rotation): 사각형 자체도 전체 회전 각도만큼 회전
        draw.rect()
            .xy(pt2(x, y))
            .wh(vec2(80.0, 80.0))
            .color(color)
            .rotate(model.rotation);
    }

    // 그리기 명령을 실제 프레임 버퍼(frame)에 적용합니다.
    // unwrap()은 렌더링 오류 시 프로그램을 중단시킵니다.
    draw.to_frame(app, &frame).unwrap();
}

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

0개의 댓글