๐ŸŽ›๏ธ :: Nannou์˜ ๋ช…์‹œ์  ์ •์˜ ๊ตฌ์กฐ์ฒด

BamgasiJMยท2025๋…„ 9์›” 27์ผ

Nannou <BASIC>

๋ชฉ๋ก ๋ณด๊ธฐ
7/41
post-thumbnail

Nannou ํ”„๋ ˆ์ž„์›Œํฌ์—์„œ ๋ช…์‹œ์ ์œผ๋กœ ์ •์˜๋œ ๊ตฌ์กฐ์ฒด๋“ค์€ ํ”„๋ ˆ์ž„์›Œํฌ์˜ ํ•ต์‹ฌ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜๋ฉฐ, ์‚ฌ์šฉ์ž๊ฐ€ ์ด๋ฆ„์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†๋Š” ๊ณ ์ •๋œ ํƒ€์ž…๋“ค์ž…๋‹ˆ๋‹ค. App๊ณผ Update ์™ธ์—๋„ Nannou๋Š” ๋‹ค์–‘ํ•œ ๊ตฌ์กฐ์ฒด์™€ ํƒ€์ž…์„ ์ œ๊ณตํ•˜์—ฌ ์ฐฝ ๊ด€๋ฆฌ, ๊ทธ๋ž˜ํ”ฝ ๋ Œ๋”๋ง, ์ด๋ฒคํŠธ ์ฒ˜๋ฆฌ ๋“ฑ์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.

Rust์—๋Š” ํด๋ž˜์Šค์˜ ๊ฐœ๋…์ด ์—†์Šต๋‹ˆ๋‹ค. ์ž์ฃผ ์“ฐ์ด๋Š” App๊ณผ Update๋Š” ํด๋ž˜์Šค๊ฐ€ ์•„๋‹ˆ๋ผ ๊ตฌ์กฐ์ฒด(struct)๋กœ ๊ตฌํ˜„๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๊ตฌ์กฐ์ฒด๋“ค์€ Nannou ๋‚ด๋ถ€์—์„œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ƒํƒœ์™€ ์—…๋ฐ์ดํŠธ ์ •๋ณด๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.
Rust์—์„œ๋Š” ๊ฐ์ฒด ์ง€ํ–ฅ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์„ ํŠธ๋ ˆ์ดํŠธ(trait)์™€ ๊ตฌ์กฐ์ฒด(struct)๋ฅผ ์กฐํ•ฉํ•ด ๊ตฌํ˜„ํ•˜๋ฉฐ, App๊ณผ Update๋„ ์ด ๋ฐฉ์‹์œผ๋กœ ์„ค๊ณ„๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

Nannou์—์„œ ๋ช…์‹œ์ ์œผ๋กœ ์ •์˜๋œ ์ฃผ์š” ๊ตฌ์กฐ์ฒด๋“ค

Nannou์—์„œ ๋ช…์‹œ์ ์œผ๋กœ ์ •์˜๋œ ์ฃผ์š” ๊ตฌ์กฐ์ฒด์—๋Š” App, Update, Frame, Draw, Window, Event, LoopMode, Sketch, Vec2/Vec3, Rgb/Rgba ๋“ฑ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋“ค์€ Nannou์˜ ํ•ต์‹ฌ API๋กœ, ์ด๋ฆ„์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†์œผ๋ฉฐ ํ”„๋ ˆ์ž„์›Œํฌ์˜ ๋™์ž‘์„ ์ œ์–ดํ•˜๋Š” ๋ฐ ํ•„์ˆ˜์ ์ž…๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž ์ •์˜ ๊ตฌ์กฐ์ฒด(์˜ˆ: Model)์™€ ๋‹ฌ๋ฆฌ, ์ด๋“ค์€ nannou::prelude์— ์ •์˜๋œ ๊ณ ์ •๋œ ํƒ€์ž…์ž…๋‹ˆ๋‹ค.


๐Ÿงฐ App

  • Nannou ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์ „๋ฐ˜์ ์ธ ์ƒํƒœ์™€ ์ปจํ…์ŠคํŠธ๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ํ•ต์‹ฌ ๊ตฌ์กฐ์ฒด์ž…๋‹ˆ๋‹ค. ์ฐฝ ์ƒ์„ฑ, ์ด๋ฒคํŠธ ๋ฃจํ”„ ๊ด€๋ฆฌ, ๋“œ๋กœ์ž‰ ์ปจํ…์ŠคํŠธ ์ œ๊ณต ๋“ฑ์˜ ๊ธฐ๋Šฅ์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

  • ์ฃผ์š” ๋ฉ”์„œ๋“œ:

    • app.new_window(): ์ƒˆ ์ฐฝ์„ ์ƒ์„ฑ.
    • app.draw(): ๋“œ๋กœ์ž‰ ์ปจํ…์ŠคํŠธ๋ฅผ ๋ฐ˜ํ™˜.
    • app.main_window(): ๋ฉ”์ธ ์ฐฝ์— ์ ‘๊ทผ.
  • ์‚ฌ์šฉ ์˜ˆ:
fn model(app: &App) -> Model {
    let _window = app.new_window().size(512, 512).view(view).build().unwrap();
    Model { /* ... */ }
}

๐Ÿงฐ Update

  • ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์ƒํƒœ ๊ฐฑ์‹  ์‹œ ์‚ฌ์šฉ๋˜๋Š” ๊ตฌ์กฐ์ฒด๋กœ, ํ”„๋ ˆ์ž„ ๊ฐ„ ์‹œ๊ฐ„ ์ •๋ณด๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. update ํ•จ์ˆ˜์˜ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ์ „๋‹ฌ๋ฉ๋‹ˆ๋‹ค.

  • ์ฃผ์š” ํ•„๋“œ:

    • since_last: ๋งˆ์ง€๋ง‰ ํ”„๋ ˆ์ž„ ์ดํ›„ ๊ฒฝ๊ณผ ์‹œ๊ฐ„ (std::time::Duration).
    • since_start: ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์‹œ์ž‘ ์ดํ›„ ๊ฒฝ๊ณผ ์‹œ๊ฐ„.
  • ์‚ฌ์šฉ ์˜ˆ:
fn update(_app: &App, model: &mut Model, update: Update) {
    model.position += update.since_last.as_secs_f32() * 100.0;
}

๐Ÿงฐ Frame

  • ๋ Œ๋”๋งํ•  ๋‹จ์ผ ํ”„๋ ˆ์ž„์„ ๋‚˜ํƒ€๋‚ด๋Š” ๊ตฌ์กฐ์ฒด์ž…๋‹ˆ๋‹ค. view ํ•จ์ˆ˜์—์„œ ๋“œ๋กœ์ž‰ ๊ฒฐ๊ณผ๋ฅผ ํ”„๋ ˆ์ž„์— ๊ธฐ๋กํ•  ๋•Œ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.
  • ์ฃผ์š” ์—ญํ• : ๋“œ๋กœ์ž‰ ๋ช…๋ น์„ ํ”„๋ ˆ์ž„์— ์ ์šฉํ•˜๊ณ , ์ด๋ฅผ ํ™”๋ฉด์— ๋ Œ๋”๋งํ•ฉ๋‹ˆ๋‹ค.
  • ์‚ฌ์šฉ ์˜ˆ:
fn view(app: &App, model: &Model, frame: Frame) {
    let draw = app.draw();
    draw.background().color(BLACK);
    draw.to_frame(app, &frame).unwrap();
}

๐Ÿงฐ Draw

  • Nannou์˜ ๋“œ๋กœ์ž‰ API๋ฅผ ์ œ๊ณตํ•˜๋Š” ๊ตฌ์กฐ์ฒด๋กœ, ๋„ํ˜•, ์„ , ํ…์Šค์ฒ˜ ๋“ฑ์„ ๊ทธ๋ฆด ๋•Œ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. app.draw()๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ์–ป์Šต๋‹ˆ๋‹ค.

  • ์ฃผ์š” ๋ฉ”์„œ๋“œ:

    • draw.ellipse(), draw.rect(), draw.line() ๋“ฑ: ๊ธฐ๋ณธ ๋„ํ˜• ๊ทธ๋ฆฌ๊ธฐ.
    • draw.to_frame(): ๋“œ๋กœ์ž‰ ๊ฒฐ๊ณผ๋ฅผ ํ”„๋ ˆ์ž„์— ์ ์šฉ.
  • ์‚ฌ์šฉ ์˜ˆ:
let draw = app.draw();
draw.ellipse().xy(vec2(0.0, 0.0)).radius(50.0).color(RED);

๐Ÿงฐ Window

  • Nannou ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์ฐฝ์„ ๋‚˜ํƒ€๋‚ด๋Š” ๊ตฌ์กฐ์ฒด์ž…๋‹ˆ๋‹ค. ์ฐฝ์˜ ํฌ๊ธฐ, ์ œ๋ชฉ, ์ด๋ฒคํŠธ ์ฒ˜๋ฆฌ ๋“ฑ์„ ์„ค์ •ํ•  ๋•Œ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

  • ์ฃผ์š” ๋ฉ”์„œ๋“œ:

    • window.size(), window.set_title(): ์ฐฝ ์†์„ฑ ์„ค์ •.
    • window.view(): ์ฐฝ์— ๋ Œ๋”๋งํ•  ๋ทฐ ํ•จ์ˆ˜ ์ง€์ •.
  • ์‚ฌ์šฉ ์˜ˆ:
let _window = app.new_window().size(800, 600).title("My App").view(view).build().unwrap();

๐Ÿงฐ Event

  • ๋งˆ์šฐ์Šค, ํ‚ค๋ณด๋“œ, ์ฐฝ ์ด๋ฒคํŠธ ๋“ฑ ๋‹ค์–‘ํ•œ ์‚ฌ์šฉ์ž ์ž…๋ ฅ๊ณผ ์‹œ์Šคํ…œ ์ด๋ฒคํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ตฌ์กฐ์ฒด์ž…๋‹ˆ๋‹ค. event ํ•จ์ˆ˜์—์„œ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.
  • ์ฃผ์š” ํ•„๋“œ: ๋‹ค์–‘ํ•œ ์ด๋ฒคํŠธ ํƒ€์ž…(์˜ˆ: MouseMoved, KeyPressed)์„ ํฌํ•จํ•˜๋Š” ์—ด๊ฑฐํ˜•(enum)๊ณผ ๊ด€๋ จ.
  • ์‚ฌ์šฉ ์˜ˆ:
fn event(_app: &App, model: &mut Model, event: Event) {
    match event {
        Event::WindowEvent { simple: Some(event), .. } => {
            if let WindowEvent::KeyPressed(Key::Space) = event {
                model.color = rgb(0.0, 1.0, 0.0); // ์ŠคํŽ˜์ด์Šค๋ฐ”๋กœ ์ƒ‰์ƒ ๋ณ€๊ฒฝ
            }
        }
        _ => {}
    }
}

๐Ÿงฐ LoopMode

  • ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๋ฃจํ”„ ๋ชจ๋“œ๋ฅผ ์„ค์ •ํ•˜๋Š” ๊ตฌ์กฐ์ฒด๋กœ, ํ”„๋ ˆ์ž„ ์—…๋ฐ์ดํŠธ ๋ฐฉ์‹(์˜ˆ: ๊ณ ์ • ํ”„๋ ˆ์ž„ ์†๋„, ์ˆ˜์š” ๊ธฐ๋ฐ˜ ๋ Œ๋”๋ง)์„ ์ œ์–ดํ•ฉ๋‹ˆ๋‹ค.
  • ์ฃผ์š” ์‚ฌ์šฉ: app.set_loop_mode(LoopMode::Rate(fps))๋กœ ํ”„๋ ˆ์ž„ ์†๋„๋ฅผ ์„ค์ •.
  • ์‚ฌ์šฉ ์˜ˆ:
fn model(app: &App) -> Model {
    app.set_loop_mode(LoopMode::Rate(60.0)); // 60 FPS๋กœ ์„ค์ •
    Model { /* ... */ }
}

๐Ÿงฐ Sketch

  • ๊ฐ„๋‹จํ•œ ์Šค์ผ€์น˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋งŒ๋“ค ๋•Œ ์‚ฌ์šฉ๋˜๋Š” ๊ตฌ์กฐ์ฒด๋กœ, nannou::sketch ๋ชจ๋“ˆ์—์„œ ์ œ๊ณต๋ฉ๋‹ˆ๋‹ค. App์„ ๋‹จ์ˆœํ™”ํ•œ ์ธํ„ฐํŽ˜์ด์Šค์ž…๋‹ˆ๋‹ค.
  • ์ฃผ์š” ์‚ฌ์šฉ: ๋น ๋ฅด๊ฒŒ ํ”„๋กœํ† ํƒ€์ดํ•‘ํ•  ๋•Œ ์œ ์šฉ.
  • ์‚ฌ์šฉ ์˜ˆ:
use nannou::prelude::*;
fn main() {
    nannou::sketch(view).run();
}
fn view(app: &App, frame: Frame) {
    let draw = app.draw();
    draw.background().color(WHITE);
    draw.to_frame(app, &frame).unwrap();
}

๐Ÿงฐ Vec2, Vec3, Point2, Point3

  • 2D ๋ฐ 3D ๋ฒกํ„ฐ์™€ ์ ์„ ๋‚˜ํƒ€๋‚ด๋Š” ๊ตฌ์กฐ์ฒด๋“ค๋กœ, ์œ„์น˜, ์ด๋™, ํšŒ์ „ ๋“ฑ์„ ์ฒ˜๋ฆฌํ•  ๋•Œ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. glam ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ ๊ฐ€์ ธ์˜จ ํƒ€์ž…์ž…๋‹ˆ๋‹ค.
  • ์ฃผ์š” ์‚ฌ์šฉ: ๊ทธ๋ž˜ํ”ฝ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ์ขŒํ‘œ์™€ ๋ณ€ํ™˜์„ ๋‹ค๋ฃฐ ๋•Œ ํ•„์ˆ˜์ .
  • ์‚ฌ์šฉ ์˜ˆ:
let position = vec2(100.0, 200.0); // 2D ๋ฒกํ„ฐ
draw.ellipse().xy(position).radius(20.0).color(BLUE);

๐Ÿงฐ Rgb, Rgba, Hsl, Hsla

  • ์ƒ‰์ƒ์„ ๋‚˜ํƒ€๋‚ด๋Š” ๊ตฌ์กฐ์ฒด๋“ค๋กœ, RGB, RGBA, HSL, HSLA ์ƒ‰์ƒ ๋ชจ๋ธ์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.
  • ์ฃผ์š” ์‚ฌ์šฉ: ๋“œ๋กœ์ž‰ ์‹œ ์ƒ‰์ƒ ์ง€์ •.
  • ์‚ฌ์šฉ ์˜ˆ:
draw.rect().w_h(100.0, 100.0).color(Rgb::new(1.0, 0.0, 0.0)); // ๋นจ๊ฐ„์ƒ‰ ์‚ฌ๊ฐํ˜•

โœ… โš™๏ธ๐Ÿ› ๏ธ๐Ÿ“„๐Ÿ“š๐ŸŽจ๐Ÿ–ผ๏ธ๐Ÿงฉ๐Ÿง ๐Ÿงฎ๐Ÿ•น๏ธ๐Ÿงฟโณ๐ŸŽ›๏ธ๐Ÿ”ฎ๐ŸŒŒ๐Ÿชฉ๐Ÿ—‚๏ธ๐Ÿ“๐Ÿงฐ๐Ÿ”’

์•„๋ณด์นด๋„
Sample
Important
Highlighting
๋น„์ƒ‰
์ ํ™ฉ์ƒ‰
purple
hot pink
yellow
์‚ด๊ตฌ์ƒ‰
orange
green
blue

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

0๊ฐœ์˜ ๋Œ“๊ธ€