
Nannou ํ๋ ์์ํฌ์์ ๋ช ์์ ์ผ๋ก ์ ์๋ ๊ตฌ์กฐ์ฒด๋ค์ ํ๋ ์์ํฌ์ ํต์ฌ ๊ธฐ๋ฅ์ ์ ๊ณตํ๋ฉฐ, ์ฌ์ฉ์๊ฐ ์ด๋ฆ์ ๋ณ๊ฒฝํ ์ ์๋ ๊ณ ์ ๋ ํ์ ๋ค์ ๋๋ค.
App๊ณผUpdate์ธ์๋ Nannou๋ ๋ค์ํ ๊ตฌ์กฐ์ฒด์ ํ์ ์ ์ ๊ณตํ์ฌ ์ฐฝ ๊ด๋ฆฌ, ๊ทธ๋ํฝ ๋ ๋๋ง, ์ด๋ฒคํธ ์ฒ๋ฆฌ ๋ฑ์ ์ง์ํฉ๋๋ค.
Rust์๋ ํด๋์ค์ ๊ฐ๋ ์ด ์์ต๋๋ค. ์์ฃผ ์ฐ์ด๋
App๊ณผUpdate๋ ํด๋์ค๊ฐ ์๋๋ผ ๊ตฌ์กฐ์ฒด(struct)๋ก ๊ตฌํ๋์ด ์์ต๋๋ค. ์ด ๊ตฌ์กฐ์ฒด๋ค์ Nannou ๋ด๋ถ์์ ์ ํ๋ฆฌ์ผ์ด์ ์ํ์ ์ ๋ฐ์ดํธ ์ ๋ณด๋ฅผ ๊ด๋ฆฌํ๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค.
Rust์์๋ ๊ฐ์ฒด ์งํฅ ํ๋ก๊ทธ๋๋ฐ์ ํธ๋ ์ดํธ(trait)์ ๊ตฌ์กฐ์ฒด(struct)๋ฅผ ์กฐํฉํด ๊ตฌํํ๋ฉฐ,App๊ณผUpdate๋ ์ด ๋ฐฉ์์ผ๋ก ์ค๊ณ๋์์ต๋๋ค.
Nannou์์ ๋ช
์์ ์ผ๋ก ์ ์๋ ์ฃผ์ ๊ตฌ์กฐ์ฒด์๋ App, Update, Frame, Draw, Window, Event, LoopMode, Sketch, Vec2/Vec3, Rgb/Rgba ๋ฑ์ด ์์ต๋๋ค. ์ด๋ค์ Nannou์ ํต์ฌ API๋ก, ์ด๋ฆ์ ๋ณ๊ฒฝํ ์ ์์ผ๋ฉฐ ํ๋ ์์ํฌ์ ๋์์ ์ ์ดํ๋ ๋ฐ ํ์์ ์
๋๋ค. ์ฌ์ฉ์ ์ ์ ๊ตฌ์กฐ์ฒด(์: Model)์ ๋ฌ๋ฆฌ, ์ด๋ค์ nannou::prelude์ ์ ์๋ ๊ณ ์ ๋ ํ์
์
๋๋ค.
AppNannou ์ ํ๋ฆฌ์ผ์ด์ ์ ์ ๋ฐ์ ์ธ ์ํ์ ์ปจํ ์คํธ๋ฅผ ๊ด๋ฆฌํ๋ ํต์ฌ ๊ตฌ์กฐ์ฒด์ ๋๋ค. ์ฐฝ ์์ฑ, ์ด๋ฒคํธ ๋ฃจํ ๊ด๋ฆฌ, ๋๋ก์ ์ปจํ ์คํธ ์ ๊ณต ๋ฑ์ ๊ธฐ๋ฅ์ ์ํํฉ๋๋ค.
์ฃผ์ ๋ฉ์๋:
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;
}
Framefn view(app: &App, model: &Model, frame: Frame) {
let draw = app.draw();
draw.background().color(BLACK);
draw.to_frame(app, &frame).unwrap();
}
DrawNannou์ ๋๋ก์ 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);
WindowNannou ์ ํ๋ฆฌ์ผ์ด์ ์ ์ฐฝ์ ๋ํ๋ด๋ ๊ตฌ์กฐ์ฒด์ ๋๋ค. ์ฐฝ์ ํฌ๊ธฐ, ์ ๋ชฉ, ์ด๋ฒคํธ ์ฒ๋ฆฌ ๋ฑ์ ์ค์ ํ ๋ ์ฌ์ฉ๋ฉ๋๋ค.
์ฃผ์ ๋ฉ์๋:
window.size(), window.set_title(): ์ฐฝ ์์ฑ ์ค์ .window.view(): ์ฐฝ์ ๋ ๋๋งํ ๋ทฐ ํจ์ ์ง์ .let _window = app.new_window().size(800, 600).title("My App").view(view).build().unwrap();
Eventevent ํจ์์์ ์ฌ์ฉ๋ฉ๋๋ค.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); // ์คํ์ด์ค๋ฐ๋ก ์์ ๋ณ๊ฒฝ
}
}
_ => {}
}
}
LoopModeapp.set_loop_mode(LoopMode::Rate(fps))๋ก ํ๋ ์ ์๋๋ฅผ ์ค์ .fn model(app: &App) -> Model {
app.set_loop_mode(LoopMode::Rate(60.0)); // 60 FPS๋ก ์ค์
Model { /* ... */ }
}
Sketchnannou::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, Point3glam ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์ ๊ฐ์ ธ์จ ํ์
์
๋๋ค.let position = vec2(100.0, 200.0); // 2D ๋ฒกํฐ
draw.ellipse().xy(position).radius(20.0).color(BLUE);
Rgb, Rgba, Hsl, HslaRGB, 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