
Nannou์์๋ Model์ ์ค์ฌ์ผ๋ก ์ฑ ์ํ๋ฅผ ๊ด๋ฆฌํฉ๋๋ค.
struct Model๋ก ํ๋๋ง ์ ๋ฆฌํ๊ณ , model, update, view ํจ์์์ ๋ก์ง์ ์ฒ๋ฆฌํฉ๋๋ค. modelํจ์์์ Model ์ธ์คํด์ค๋ฅผ ์์ฑํ๊ณ update, event, view ํจ์๊ฐ ์ด Model์ ๋ฐ์ดํฐ๋ฅผ ๋ณ๊ฒฝํ๊ฑฐ๋ ์ฝ์ด์ ๋ก์ง์ ์ฒ๋ฆฌํฉ๋๋ค.๋ฐ๋ฉด impl Model๋ก ๋ฉ์๋๋ฅผ ์ถ๊ฐํ๋ฉด ์ํ์ ๋์์ ์บก์ํํ์ฌ OOP ์คํ์ผ์ ๋์
ํ ์๋ ์์ต๋๋ค.
Model ๋ด๋ถ์ ๋์(๋ฉ์๋)๋ฅผ ์บก์ํํ๊ธฐ ๋๋ฌธ์ ์ฌ์ฌ์ฉ์ฑ์ด ์ฆ๊ฐํฉ๋๋ค.update/view์์๋ ์ฌ์ ํ &mut Model ๋๋ &Model์ ๋ฐ์ ๋ด๋ถ ๋ฉ์๋๋ฅผ ํธ์ถํฉ๋๋ค.๋ฐํ์ ์ฑ๋ฅ ์ฐจ์ด๋ ๊ฑฐ์ ์์ผ๋ฏ๋ก (๋์ผํ ๋ฐ์ดํธ ์ฝ๋๋ก ์ปดํ์ผ ๋จ) ์ค๊ณ ๋ฐฉ์์ ๋ฐ๋ผ ์ ํํ๋ฉด ๋ฉ๋๋ค.
struct & free functions (์ ํต์ ์ธ nannou ์คํ์ผ)
Model์ ๋จ์ํ ๋ฐ์ดํฐ ์ปจํ ์ด๋๋ก ์ฌ์ฉํฉ๋๋ค.
์ด๊ธฐํ๋ model ํจ์, ์ํ ๋ณ๊ฒฝ์ update, ๋ ๋๋ง์ view ๊ฐ์ Nannou๊ฐ ์ ๊ณตํ๋ ๋ฉ์ธ ์ฝ๋ฐฑ ํจ์์ ๋ด๋ถ์์ ์ฒ๋ฆฌํฉ๋๋ค. ๋ก์ง์ด ํจ์ ์ค์ฌ์ผ๋ก ๋ถ๋ฆฌ๋์ด ๊ฐ๋จํฉ๋๋ค.
์ ์ญ ํจ์๋ก ๊ตฌ์ฑํ๋ฉด ๊ฐ ์ฝ๋ฐฑ์ ์
์ถ๋ ฅ(์๊ทธ๋์ฒ)์ด ํ๋์ ๋ณด์ด๋ ์ฅ์ ์ด ์์ต๋๋ค.
๋ค๋ง ์ํ ๋ณ๊ฒฝ์ ๋ํ ๋ก์ง์ด ๋ถ์ฐ๋์ด ์ ์ง๋ณด์๊ฐ ์ด๋ ค์์ง๊ณ , ๋์ผํ ์ํ์ ๋ํ ๋ก์ง์ ์ฌ์ฌ์ฉํ๊ธฐ ์ด๋ ต์ต๋๋ค.
๋ํ ๊ตฌ์กฐ์ฒด ๋ด๋ถ์ ๊ตฌํ์ ๋ฐ์์ ์ฝ๊ฒ ๋ค๋ฃจ๊ฒ ๋๋ฏ๋ก ์บก์ํ๊ฐ ์ฝํฉ๋๋ค.
use nannou::prelude::*;
struct Model {
time: f32,
}
fn main() {
nannou::app(model).update(update).run();
}
fn model(app: &App) -> Model {
app.new_window().size(800, 800).view(view).build().unwrap();
Model { time: 0.0 }
}
fn update(_app: &App, model: &mut Model, update: Update) {
model.time += update.since_last.as_secs_f32();
}
fn view(app: &App, model: &Model, frame: Frame) {
let draw = app.draw();
draw.background().color(WHITE);
let radius = (model.time.sin() * 50.0 + 100.0) as f32;
draw.ellipse().radius(radius).color(BLACK);
draw.to_frame(app, &frame).unwrap();
}
use nannou::prelude::*;
struct Model {
positions: Vec<Vec2>,
speeds: Vec<Vec2>,
count: usize,
}
fn main() {
nannou::app(model).update(update).run();
}
fn model(app: &App) -> Model {
let _window = app.new_window().size(800, 800).view(view).build().unwrap();
let count = 200;
let mut positions = Vec::with_capacity(count);
let mut speeds = Vec::with_capacity(count);
for _ in 0..count {
positions.push(vec2(
random_range(-400.0, 400.0),
random_range(-400.0, 400.0),
));
speeds.push(vec2(
random_range(-1.0, 1.0),
random_range(-1.0, 1.0),
));
}
Model { positions, speeds, count }
}
fn update(_app: &App, model: &mut Model, _update: Update) {
for i in 0..model.count {
model.positions[i] += model.speeds[i];
// ํ๋ฉด ๋ฐ์ด๋ฉด ๋ฐ์ฌ
if model.positions[i].x.abs() > 400.0 {
model.speeds[i].x *= -1.0;
}
if model.positions[i].y.abs() > 400.0 {
model.speeds[i].y *= -1.0;
}
}
}
fn view(app: &App, model: &Model, frame: Frame) {
let draw = app.draw();
if frame.nth() == 0 {
draw.background().color(BLACK);
} else {
draw.rect()
.x_y(0.0, 0.0)
.w_h(800.0, 800.0)
.rgba(0.0, 0.0, 0.0, 0.06);
}
for &pos in &model.positions {
draw.ellipse().xy(pos).w_h(6.0, 6.0).rgba(1.0, 0.6, 0.2, 0.9);
}
draw.to_frame(app, &frame).unwrap();
}
use nannou::prelude::*;
fn main() {
nannou::app(model).update(update).run();
}
// 1. Model ๊ตฌ์กฐ์ฒด: ์ ํ๋ฆฌ์ผ์ด์
์ '์ํ' (๋ฐ์ดํฐ)๋ง ์ ์ํฉ๋๋ค.
struct Model {
x_position: f32,
speed: f32,
}
// 2. model ํจ์: Model์ ์ด๊ธฐ ์ํ๋ฅผ ์ค์ ํ๊ณ ๋ฐํํฉ๋๋ค.
fn model(app: &App) -> Model {
app.new_window().view(view).build().unwrap();
Model {
x_position: 0.0,
speed: 2.0,
}
}
// 3. update ํจ์: 'Model'์ ์ง์ ์์ ํ์ฌ ๋ก์ง์ ์ฒ๋ฆฌํฉ๋๋ค.
// ๋ก์ง์ด ๋ณต์กํด์ง๋ฉด ์ด ํจ์๊ฐ ๋งค์ฐ ๊ธธ์ด์ง๋๋ค.
fn update(app: &App, model: &mut Model, _update: Update) {
let win = app.window_rect();
// x ์์น ๋ณ๊ฒฝ ๋ก์ง
model.x_position += model.speed;
// ๋ฒฝ์ ๋ฟ์ผ๋ฉด ๋ฐฉํฅ ์ ํ
if model.x_position > win.right() || model.x_position < win.left() {
model.speed *= -1.0;
}
}
// 4. view ํจ์: 'Model'์ ๋ฐ์ดํฐ๋ฅผ ์ฝ์ด ํ๋ฉด์ ๊ทธ๋ฆฝ๋๋ค.
fn view(app: &App, model: &Model, frame: Frame) {
let draw = app.draw();
draw.background().color(PLUM);
// model์ x_position ๊ฐ์ ์ง์ ์ฝ์ด์ ์ฌ์ฉ
draw.ellipse()
.x_y(model.x_position, 0.0)
.radius(50.0)
.color(STEELBLUE);
draw.to_frame(app, &frame).unwrap();
}
impl Model (๋ฉ์๋ ํฌํจ โ OOP ์คํ์ผ)
Model์ ๋ฉ์๋๋ฅผ ๊ตฌํํด ๋ก์ง์ ์บก์ํํฉ๋๋ค.
Model ๊ตฌ์กฐ์ฒด์ ๋ฐ์ดํฐ๋ฟ๋ง ์๋๋ผ impl Model { ... } ๋ธ๋ก์ ์ฌ์ฉํด ํด๋น ๋ฐ์ดํฐ๋ฅผ ์กฐ์ํ๋ ๋ฉ์๋(ํ์)๋ฅผ ํจ๊ป ์ ์ํฉ๋๋ค.
update์ view ๊ฐ์ ์ฝ๋ฐฑ ํจ์๋ ์ด ๋ฉ์๋๋ฅผ ํธ์ถํ๋ ์ญํ ๋ง ๋ด๋นํ๊ฒ ๋ฉ๋๋ค.
์ํ์ ๋์์ด ๊ฐ์ฒด ์์ ๋ชจ์ฌ์ OOP-like ๊ตฌ์กฐ(์: ์ ๋๋ฉ์ด์
๋ก์ง์ Modle::animate ๋ฉ์๋๋ก ์ด๋)๋ฅผ ๋ง๋ค๊ธฐ ๋๋ฌธ์ ์ํ์ ๋์์ ํ ๊ณณ์ ๋ฌถ์ด ๊ฐ๋
์ฑ๊ณผ ์ ์ง๋ณด์์ฑ์ด ๋์ต๋๋ค.
๋ด๋ถ์ ๋ถ๋ณ/๊ฐ๋ณ ๊ท์น(&self, &mut self)์ด ๋ช
ํํฉ๋๋ค.
๋ณต์กํ ์ ๋๋ฉ์ด์
์ด๋ ์คํ ๋ก์ง์ ๋ฉ์๋๋ก ์ถ์ํํด์ ๋์ค์ ์ฌ์ฌ์ฉํ๊ธฐ ์ฉ์ดํฉ๋๋ค.
use nannou::prelude::*;
struct Model {
time: f32,
}
impl Model {
fn new() -> Self {
Self { time: 0.0 }
}
fn animate(&mut self, delta: f32) {
self.time += delta;
}
fn draw_circle(&self, draw: &Draw) {
// ๋ฐฐ๊ฒฝ ์ง์ฐ๊ธฐ
draw.background().color(WHITE);
// time์ ์ด์ฉํด ๋ฐ์ง๋ฆ ์ง๋
let radius = (self.time.sin() * 50.0 + 100.0) as f32;
// ์ค์ฌ ์ ๊ทธ๋ฆฌ๊ธฐ
draw.ellipse().radius(radius).color(BLACK);
}
}
fn main() {
nannou::app(model).update(update).run();
}
fn model(app: &App) -> Model {
app.new_window().size(800, 800).view(view).title("Animated Circle").build().unwrap();
Model::new()
}
fn update(_app: &App, model: &mut Model, update: Update) {
let delta = update.since_last.as_secs_f32();
model.animate(delta);
}
fn view(app: &App, model: &Model, frame: Frame) {
let draw = app.draw();
// ๋ชจ๋ธ์ ์ ์๋ ๊ทธ๋ฆฌ๊ธฐ ๋ก์ง ํธ์ถ
model.draw_circle(&draw);
// ํ๋ ์ ์ ์ถ
draw.to_frame(app, &frame).unwrap();
}
use nannou::prelude::*;
struct Model {
positions: Vec<Vec2>,
speeds: Vec<Vec2>,
count: usize,
}
impl Model {
// ์์ฑ์ ์ญํ
fn new(win_w: f32, win_h: f32, count: usize) -> Self {
let mut positions = Vec::with_capacity(count);
let mut speeds = Vec::with_capacity(count);
for _ in 0..count {
positions.push(vec2(
random_range(-win_w * 0.5, win_w * 0.5),
random_range(-win_h * 0.5, win_h * 0.5),
));
speeds.push(vec2(
random_range(-1.0, 1.0),
random_range(-1.0, 1.0),
));
}
Model { positions, speeds, count }
}
// ์ํ ์
๋ฐ์ดํธ๋ฅผ ์บก์ํ
fn step(&mut self, win_w: f32, win_h: f32) {
for i in 0..self.count {
self.positions[i] += self.speeds[i];
if self.positions[i].x.abs() > win_w * 0.5 {
self.speeds[i].x *= -1.0;
}
if self.positions[i].y.abs() > win_h * 0.5 {
self.speeds[i].y *= -1.0;
}
}
}
// ๋ ๋๋ง ๋์ฐ๋ฏธ (view ๋ด๋ถ์์ ํธ์ถ)
fn draw(&self, draw: &Draw) {
for &pos in &self.positions {
draw.ellipse().xy(pos).w_h(6.0, 6.0).rgba(0.2, 0.9, 1.0, 0.9);
}
}
}
fn main() {
nannou::app(model).update(update).run();
}
fn model(app: &App) -> Model {
let _window = app.new_window().size(800, 800).view(view).build().unwrap();
Model::new(800.0, 800.0, 200)
}
fn update(app: &App, model: &mut Model, _update: Update) {
let [w, h] = {
let rect = app.main_window().rect();
[rect.w(), rect.h()]
};
model.step(w, h); // ๋ฉ์๋๋ก ์บก์ํ๋ ์
๋ฐ์ดํธ ํธ์ถ
}
fn view(app: &App, model: &Model, frame: Frame) {
let draw = app.draw();
if frame.nth() == 0 {
draw.background().color(BLACK);
} else {
draw.rect()
.w_h(800.0, 800.0)
.rgba(0.0, 0.0, 0.0, 0.06);
}
model.draw(&draw); // ์บก์ํ๋ ๋ ๋ ํธ์ถ
draw.to_frame(app, &frame).unwrap();
}
use nannou::prelude::*;
fn main() {
nannou::app(model).update(update).run();
}
// 1. Model ๊ตฌ์กฐ์ฒด: ๋ฐ์ดํฐ(์ํ) ์ ์
struct Model {
x_position: f32,
speed: f32,
}
// 2. impl Model: Model๊ณผ ๊ด๋ จ๋ 'ํ์'(๋ฉ์๋)๋ฅผ ์ ์ํฉ๋๋ค.
// ์ด๊ฒ์ด OOP(๊ฐ์ฒด ์งํฅ ํ๋ก๊ทธ๋๋ฐ)์ ์บก์ํ์ ์ ์ฌํฉ๋๋ค.
impl Model {
// 'model' ํจ์์ ์ญํ ์ ์ด ๋ฉ์๋๊ฐ ๋์ ํฉ๋๋ค. (์์ฑ์ ์ญํ )
fn new(app: &App) -> Model {
app.new_window().view(view).build().unwrap();
Model {
x_position: 0.0,
speed: 2.0,
}
}
// 'update' ํจ์์ ๋ก์ง์ ์ด ๋ฉ์๋๋ก ์ฎ๊ฒผ์ต๋๋ค.
fn update_position(&mut self, app: &App) {
let win = app.window_rect();
self.x_position += self.speed;
if self.x_position > win.right() || self.x_position < win.left() {
self.speed *= -1.0;
}
}
// 'view' ํจ์์ ๋ก์ง์ ์ด ๋ฉ์๋๋ก ์ฎ๊ฒผ์ต๋๋ค.
fn draw_view(&self, app: &App, frame: Frame) {
let draw = app.draw();
draw.background().color(PLUM);
draw.ellipse()
.x_y(self.x_position, 0.0)
.radius(50.0)
.color(STEELBLUE);
draw.to_frame(app, &frame).unwrap();
}
}
// 3. Nannou ์ฝ๋ฐฑ ํจ์๋ค: ์ด์ ๋งค์ฐ ๋จ์ํด์ง๋๋ค.
// ๋จ์ํ Model์ ์ ์ ํ ๋ฉ์๋๋ฅผ 'ํธ์ถ'๋ง ํฉ๋๋ค.
fn model(app: &App) -> Model {
Model::new(app) // Model์ 'new' ๋ฉ์๋ ํธ์ถ
}
fn update(app: &App, model: &mut Model, _update: Update) {
model.update_position(app); // Model์ 'update_position' ๋ฉ์๋ ํธ์ถ
}
fn view(app: &App, model: &Model, frame: Frame) {
model.draw_view(app, frame); // Model์ 'draw_view' ๋ฉ์๋ ํธ์ถ
}
โ โ๏ธ๐ ๏ธ๐๐๐จ๐ผ๏ธ๐งฉ๐ง ๐งฎ๐น๏ธ๐งฟโณ๐๏ธ๐ฎ๐๐ชฉ๐๏ธ๐๐งฐ๐
์๋ณด์นด๋
Sample
Important
Highlighting
๋น์
์ ํฉ์
purple
hot pink
yellow
์ด๊ตฌ์
orange
green
blue