๐ŸŽ›๏ธ :: app.time() ์ดํ•ดํ•˜๊ธฐ

BamgasiJMยท2025๋…„ 10์›” 14์ผ

Nannou <BASIC>

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

Nannou์—์„œ app.time() ์™„๋ฒฝ ์ดํ•ดํ•˜๊ธฐ

์‹œ๊ฐ„์— ๋”ฐ๋ผ ๋ณ€ํ™”ํ•˜๋Š” ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ๊ตฌํ˜„ํ•  ๋•Œ ๊ฐ€์žฅ ์ž์ฃผ ์‚ฌ์šฉํ•˜๋Š” ๋ฉ”์„œ๋“œ๊ฐ€ ๋ฐ”๋กœ app.time()์ด๋‹ค.
์ด ๋ฉ”์„œ๋“œ๋Š” ๋‹จ์ˆœํžˆ โ€œํ˜„์žฌ ๊ฒฝ๊ณผ ์‹œ๊ฐ„โ€์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒƒ ๊ฐ™์ง€๋งŒ,
์ •ํ™•ํžˆ ์–ธ์ œ, ์–ด๋–ค ๋‹จ์œ„๋กœ, ์–ด๋–ป๊ฒŒ ๊ฐฑ์‹ ๋˜๋Š”์ง€๋ฅผ ์ดํ•ดํ•˜๋ฉด ํ›จ์”ฌ ๋” ์œ ์—ฐํ•œ ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.

๐Ÿงฉ 1. app.time()์˜ ๊ธฐ๋ณธ ๊ฐœ๋…

app.time()์€ Nannou์˜ App ๊ตฌ์กฐ์ฒด์— ํฌํ•จ๋œ ๋ฉ”์„œ๋“œ๋กœ,
์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์‹œ์ž‘๋œ ์ดํ›„ ๊ฒฝ๊ณผํ•œ ์‹œ๊ฐ„์„ ์ดˆ ๋‹จ์œ„(f32)๋กœ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

let t = app.time();
  • ๋ฐ˜ํ™˜๊ฐ’ ํƒ€์ž…: f32
  • ๋‹จ์œ„: ์ดˆ(seconds)
  • ๊ธฐ์ค€์ : app ์‹คํ–‰(์œˆ๋„์šฐ ์ƒ์„ฑ) ์‹œ์ 

์ฆ‰, ํ”„๋กœ๊ทธ๋žจ์ด ์‹คํ–‰๋œ ํ›„๋ถ€ํ„ฐ ํ˜„์žฌ๊นŒ์ง€์˜ ๋ˆ„์  ์‹œ๊ฐ„์ด์•ผ.
์ด ์‹œ๊ฐ„์€ ํ”„๋ ˆ์ž„๊ณผ ๊ด€๊ณ„์—†์ด ์ง€์†์ ์œผ๋กœ ์ฆ๊ฐ€ํ•˜๊ธฐ ๋•Œ๋ฌธ์—,
ํ”„๋ ˆ์ž„ ๋“œ๋ž์ด ์žˆ๋”๋ผ๋„ ์ „์ฒด ์‹œ๊ฐ„ ํ๋ฆ„์€ ์ผ์ •ํ•˜๊ฒŒ ์œ ์ง€๋ผ.


๐Ÿง  2. ๋‚ด๋ถ€ ๋™์ž‘ ์›๋ฆฌ

Nannou๋Š” ๋‚ด๋ถ€์ ์œผ๋กœ ํ”„๋ ˆ์ž„ ๋ฃจํ”„(ํ”„๋ ˆ์ž„ ๋‹จ์œ„ ์—…๋ฐ์ดํŠธ)๋ฅผ ๊ด€๋ฆฌํ•˜์ง€๋งŒ,
app.time()์€ ํ”„๋ ˆ์ž„ ๋ฃจํ”„์™€ ๋ณ„๊ฐœ๋กœ ์‹œ์Šคํ…œ์˜ ์‹ค์ œ ๊ฒฝ๊ณผ ์‹œ๊ฐ„์„ ๊ธฐ๋ฐ˜์œผ๋กœ ๊ฐฑ์‹ ๋œ๋‹ค.

ํ•ญ๋ชฉ๋‚ด์šฉ
๋ฐ˜ํ™˜ ํƒ€์ž… / ํ•„๋“œ ํƒ€์ž…f32 โ€” App.time ํ•„๋“œ๊ฐ€ f32 ํƒ€์ž…์œผ๋กœ ์ •์˜๋˜์–ด ์žˆ์Œ (docs.rs)
์˜๋ฏธ์•ฑ์ด ์‹œ์ž‘๋œ ์ดํ›„ ํ๋ฅธ ์‹œ๊ฐ„(์ดˆ ๋‹จ์œ„)
์ œ๊ณต ์ด์œ app.duration.since_start.secs()๋ฅผ ๋งค๋ฒˆ ํ˜ธ์ถœํ•˜์ง€ ์•Š๊ณ  ๊ฐ„ํŽธํ•˜๊ฒŒ ์ ‘๊ทผํ•˜๋ ค๋Š” ์šฉ๋„ (docs.rs)
ํ•œ๊ณ„์žฅ์‹œ๊ฐ„ ์‹คํ–‰์—๋Š” ๋ถ€๋™์†Œ์ˆ˜์  ์ •๋ฐ€๋„ ์†์‹ค ๊ฐ€๋Šฅ์„ฑ ์žˆ์Œ โ€” ๋ฌธ์„œ์—์„œ ๊ถŒ์žฅํ•˜์ง€ ์•Š์Œ (docs.rs)
๋” ์ •๋ฐ€ํ•œ ๋Œ€์•ˆapp.duration.since_start ๋˜๋Š” app.duration.since_prev_update ๋“ฑ Duration ๊ธฐ๋ฐ˜ ํ•„๋“œ ์‚ฌ์šฉ (docs.rs)
์‹œ๊ฐ„ ์œ ํ‹ธ๋ฆฌํ‹ฐnannou::time ๋ชจ๋“ˆ์—์„œ DurationF64 ๋“ฑ Duration โ†’ f64 ๋ณ€ํ™˜ ์œ ํ‹ธ๋ฆฌํ‹ฐ ์ œ๊ณต (docs.rs)

๐Ÿ’ก ์ฐธ๊ณ 
Nannou๋Š” ๋‚ด๋ถ€์ ์œผ๋กœ App ๊ตฌ์กฐ์ฒด์— Instant::now()๋ฅผ ๊ธฐ๋กํ•ด๋‘๊ณ ,
app.time() ํ˜ธ์ถœ ์‹œ Instant::now() - start_time ๊ฐ’์„ ์ดˆ ๋‹จ์œ„๋กœ ๋ณ€ํ™˜ํ•ด ๋ฐ˜ํ™˜ํ•œ๋‹ค.


โฑ๏ธ 3. ์ž์ฃผ ์“ฐ์ด๋Š” ํŒจํ„ด

๐ŸŽต ์˜ˆ์ œ 1. ์‚ฌ์ธํŒŒ ์›€์ง์ž„ ๋งŒ๋“ค๊ธฐ

fn view(app: &App, _model: &Model, frame: Frame) {
    let draw = app.draw();
    draw.background().color(BLACK);

    let t = app.time();
    let x = (t * 2.0).sin() * 200.0;
    let y = (t * 3.0).cos() * 200.0;

    draw.ellipse()
        .x_y(x, y)
        .radius(20.0)
        .color(RED);

    draw.to_frame(app, &frame).unwrap();
}
fn view(app: &App, _model: &Model, frame: Frame) {
    let draw = app.draw();

    // ์•ฑ ์‹œ์ž‘ ํ›„ ๊ฒฝ๊ณผ๋œ ์ดˆ
    let t = app.time;

    // t๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์›€์ง์ž„์ด๋‚˜ ์• ๋‹ˆ๋ฉ”์ด์…˜ ์ฒ˜๋ฆฌ
    let center = pt2(t.cos(), t.sin()) * 100.0;
    draw.rect()
        .x_y(center.x, center.y)
        .w_h(100.0, 100.0);

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

โžก๏ธ app.time()์œผ๋กœ ์–ป์€ t๋ฅผ sin๊ณผ cos ํ•จ์ˆ˜์— ์ ์šฉํ•˜๋ฉด,
์‹œ๊ฐ„์— ๋”ฐ๋ผ ์ฃผ๊ธฐ์ ์œผ๋กœ ์›€์ง์ด๋Š” ํŒจํ„ด์„ ์†์‰ฝ๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.

๐ŸŒˆ ์˜ˆ์ œ 2. ์ปฌ๋Ÿฌ ์• ๋‹ˆ๋ฉ”์ด์…˜

fn view(app: &App, _model: &Model, frame: Frame) {
    let draw = app.draw();
    draw.background().color(BLACK);

    let t = app.time();
    let hue = (t * 30.0) % 360.0;
    let color = hsv(hue / 360.0, 1.0, 1.0);

    draw.rect()
        .w_h(300.0, 300.0)
        .color(color);

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

โžก๏ธ ์‹œ๊ฐ„ ๊ธฐ๋ฐ˜์œผ๋กœ ์ƒ‰์ƒ(Hue)์„ ์ˆœํ™˜์‹œ์ผœ,
์ง€์†์ ์œผ๋กœ ๋ณ€ํ™”ํ•˜๋Š” ์‹œ๊ฐ์  ๋ฆฌ๋“ฌ์„ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.


โš™๏ธ 4. app.time()๊ณผ update()์˜ ์ฐจ์ด

๋ณดํ†ต Nannou ํ”„๋กœ์ ํŠธ๋Š” ์•„๋ž˜ ๊ตฌ์กฐ๋ฅผ ๊ฐ€์ง„๋‹ค.

fn main() {
    nannou::app(model).update(update).run();
}
  • update()๋Š” ๋งค ํ”„๋ ˆ์ž„๋งˆ๋‹ค ํ˜ธ์ถœ๋˜๋Š” ํ•จ์ˆ˜๋‹ค.

  • app.time()์€ ์ „์—ญ ์‹œ๊ฐ„์œผ๋กœ, ํ”„๋ ˆ์ž„๊ณผ ๊ด€๊ณ„์—†์ด ํ˜๋Ÿฌ๊ฐ„ ์‹œ๊ฐ„์„ ๋‚˜ํƒ€๋‚ธ๋‹ค.

๊ตฌ๋ถ„app.time()update()
์—ญํ• ๊ฒฝ๊ณผ ์‹œ๊ฐ„ ๋ฐ˜ํ™˜์ƒํƒœ ๊ฐฑ์‹  ๋กœ์ง ์ฒ˜๋ฆฌ
๋‹จ์œ„์ดˆ ๋‹จ์œ„(f64)ํ”„๋ ˆ์ž„ ๋‹จ์œ„
๊ฐฑ์‹  ์ฃผ๊ธฐ์‹ค์‹œ๊ฐ„FPS ์˜์กด
์šฉ๋„์• ๋‹ˆ๋ฉ”์ด์…˜, ์ฃผ๊ธฐ ์ œ์–ดํŒŒํ‹ฐํด, ๋ฌผ๋ฆฌ ๊ณ„์‚ฐ ๋“ฑ

๋‘˜์„ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๋ฉด
โ€œ์‹œ๊ฐ„ ๊ธฐ๋ฐ˜ + ํ”„๋ ˆ์ž„ ๊ธฐ๋ฐ˜โ€์˜ ํ•˜์ด๋ธŒ๋ฆฌ๋“œ ์—…๋ฐ์ดํŠธ๊ฐ€ ๊ฐ€๋Šฅํ•˜๋‹ค.


๐Ÿ” 5. ๋ณ€ํ˜• ํ™œ์šฉ: app.elapsed_frames()

app.time()์ด ์ดˆ ๋‹จ์œ„๋ผ๋ฉด,
app.elapsed_frames()๋Š” ํ”„๋ ˆ์ž„ ์นด์šดํ„ฐ๋‹ค.

let frame_count = app.elapsed_frames();
  • ๋‹จ์œ„: ํ”„๋ ˆ์ž„ ์ˆ˜ (์ •์ˆ˜ํ˜• u64)

  • FPS๊ฐ€ ์ผ์ •ํ•˜๋ฉด app.time()๊ณผ ๋น„๋ก€ ๊ด€๊ณ„

๐Ÿ’ก ์˜ˆ๋ฅผ ๋“ค์–ด FPS๊ฐ€ 60์ด๋ผ๋ฉด,
app.elapsed_frames() โ‰ˆ app.time() * 60.0

๋‘˜์„ ํ•จ๊ป˜ ์จ์„œ, ํ”„๋ ˆ์ž„ ๊ธฐ๋ฐ˜ ํƒ€์ด๋ฐ ์ œ์–ด๋„ ๊ฐ€๋Šฅํ•˜๋‹ค.


โš ๏ธ 6. ์ฃผ์˜ํ•  ์ 

  1. app.time()์€ ๋ฉˆ์ถ”์ง€ ์•Š๋Š”๋‹ค.

    • ์œˆ๋„์šฐ๊ฐ€ ์ผ์‹œ์ •์ง€๋˜๋”๋ผ๋„, app.time()์€ ๊ณ„์† ์ฆ๊ฐ€ํ•  ์ˆ˜ ์žˆ๋‹ค.
    • ์ผ์‹œ์ •์ง€ ๊ฐ€๋Šฅํ•œ ํƒ€์ด๋จธ๋ฅผ ์›ํ•œ๋‹ค๋ฉด ๋ณ„๋„ ๋ณ€์ˆ˜๋ฅผ ๋งŒ๋“ค์–ด delta_time์„ ๋”ํ•ด์ฃผ๋Š” ๋ฐฉ์‹์ด ํ•„์š”ํ•˜๋‹ค.
  2. ๋ฆฌ์…‹ ๋ถˆ๊ฐ€๋Šฅ

    • app.time() ์ž์ฒด๋Š” ์ดˆ๊ธฐํ™” ํ›„ ๋ณ€๊ฒฝ ๋ถˆ๊ฐ€๋Šฅ.

    • ๋ฆฌ์…‹์ด ํ•„์š”ํ•˜๋ฉด start_time = app.time() ํ˜•ํƒœ๋กœ ๊ธฐ์ค€์ ์„ ์ˆ˜๋™ ์ €์žฅํ•ด์•ผ ํ•œ๋‹ค.

  3. ๋ถ€๋™์†Œ์ˆ˜์  ์˜ค์ฐจ

    • ๋งค์šฐ ๊ธด ๋Ÿฐํƒ€์ž„(์ˆ˜์‹œ๊ฐ„ ์ด์ƒ)์—์„œ๋Š” f64์˜ ์˜ค์ฐจ๊ฐ€ ๋ˆ„์ ๋  ์ˆ˜ ์žˆ๋‹ค.

    • ์ผ๋ฐ˜์ ์ธ ์ œ๋„ˆ๋ ˆ์ดํ‹ฐ๋ธŒ ์•„ํŠธ์—์„œ๋Š” ๋ฌด์‹œํ•ด๋„ ๋ฌด๋ฐฉํ•˜๋‹ค.


๐Ÿงฎ 7. ์ง์ ‘ ๋ฆฌ์…‹ ๊ฐ€๋Šฅํ•œ ํƒ€์ด๋จธ ๊ตฌํ˜„ ์˜ˆ์‹œ

struct Model {
    start_time: f64,
}

fn model(app: &App) -> Model {
    Model {
        start_time: app.time(),
    }
}

fn view(app: &App, model: &Model, frame: Frame) {
    let t = app.time() - model.start_time; // ๋ฆฌ์…‹ ๊ฐ€๋Šฅํ•œ ์ƒ๋Œ€ ์‹œ๊ฐ„
    let draw = app.draw();
    draw.background().color(BLACK);

    let x = (t * 2.0).sin() * 200.0;
    draw.ellipse().x_y(x, 0.0).radius(30.0).color(WHITE);

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

โžก๏ธ model.start_time์„ ๊ธฐ์ค€์ ์œผ๋กœ ๋‘๋ฉด,
์–ธ์ œ๋“ ์ง€ start_time์„ ๊ฐฑ์‹ ํ•˜์—ฌ ํƒ€์ด๋จธ๋ฅผ ๋ฆฌ์…‹ํ•  ์ˆ˜ ์žˆ๋‹ค.


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

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