๐ŸŽ›๏ธ :: Rect ๊ตฌ์กฐ์ฒด

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

Nannou <BASIC>

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

nannou์˜ Rect ๊ตฌ์กฐ์ฒด๋Š” 2D ์‚ฌ๊ฐํ˜•์„ ํ‘œํ˜„ํ•˜๋Š” ํ•ต์‹ฌ์ ์ธ ํƒ€์ž…์ž…๋‹ˆ๋‹ค.

๐Ÿงฉ Rect ๊ตฌ์กฐ์ฒด ๊ฐœ์š”

Rect๋Š” ์ค‘์‹ฌ์ (center)๊ณผ ํฌ๊ธฐ(wh) ๋กœ ์ •์˜๋˜๋Š” ์‚ฌ๊ฐํ˜•์œผ๋กœ, ๊ทธ๋ž˜ํ”ฝ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์—์„œ ํ™”๋ฉด ์˜์—ญ, ๊ฒฝ๊ณ„ ์ƒ์ž ๋“ฑ์„ ํ‘œํ˜„ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.


๐Ÿงฉ ์ฃผ์š” ์ƒ์„ฑ ๋ฐฉ๋ฒ•

use nannou::prelude::*;

// ๋‹ค์–‘ํ•œ ๋ฐฉ๋ฒ•์œผ๋กœ Rect ์ƒ์„ฑ
let rect1 = Rect::from_wh(vec2(100.0, 50.0));          // ํฌ๊ธฐ๋กœ๋ถ€ํ„ฐ (์ค‘์‹ฌ์€ (0,0))
let rect2 = Rect::from_corners(pt2(-50.0, -25.0), pt2(50.0, 25.0)); // ๋ชจ์„œ๋ฆฌ๋กœ๋ถ€ํ„ฐ
let rect3 = Rect::from_x_y_w_h(10.0, 20.0, 100.0, 50.0); // ์œ„์น˜์™€ ํฌ๊ธฐ๋กœ๋ถ€ํ„ฐ
let rect4 = Rect::from_w_h(200.0, 100.0);              // ๋„ˆ๋น„, ๋†’์ด๋กœ๋ถ€ํ„ฐ

๐Ÿงฉ ์ฃผ์š” ํ•„๋“œ์™€ ๋ฉ”์„œ๋“œ

๐Ÿ”ธ ๊ธฐ๋ณธ ์†์„ฑ

let win = app.window_rect();

// ์ค‘์‹ฌ์ ๊ณผ ํฌ๊ธฐ
let center: Point2 = win.xy();     // ์ค‘์‹ฌ์  (0.0, 0.0)
let size: Vec2 = win.wh();         // ํฌ๊ธฐ (Vec2)
let width: f32 = win.w();          // ๋„ˆ๋น„
let height: f32 = win.h();         // ๋†’์ด

// ๋ชจ์„œ๋ฆฌ ์ขŒํ‘œ
let left: f32 = win.left();        // ์™ผ์ชฝ X
let right: f32 = win.right();      // ์˜ค๋ฅธ์ชฝ X  
let top: f32 = win.top();          // ์œ„์ชฝ Y
let bottom: f32 = win.bottom();    // ์•„๋ž˜์ชฝ Y

// ๋ชจ์„œ๋ฆฌ ์ ๋“ค
let top_left: Point2 = win.top_left();
let top_right: Point2 = win.top_right();
let bottom_left: Point2 = win.bottom_left();
let bottom_right: Point2 = win.bottom_right();

๐Ÿ”ธ ๋ฒ”์œ„ ๊ด€๋ จ ๋ฉ”์„œ๋“œ

// ๊ฒฝ๊ณ„ ํ™•์ธ
let point = pt2(50.0, 30.0);
let contains: bool = win.contains(point); // ์ ์ด ๋‚ด๋ถ€์— ์žˆ๋Š”์ง€ ํ™•์ธ

// ๊ต์ฐจ ํ™•์ธ
let other_rect = Rect::from_wh(vec2(50.0, 50.0));
let intersection: Option<Rect> = win.intersect(other_rect); // ๊ต์ฐจ ์˜์—ญ

// ํŒจ๋”ฉ ์ ์šฉ
let padded = win.pad(10.0);        // ๋ชจ๋“  ๋ฐฉํ–ฅ ํŒจ๋”ฉ
let padded_top = win.pad_top(5.0); // ์œ„์ชฝ๋งŒ ํŒจ๋”ฉ

๐Ÿ”ธ ๋ณ€ํ˜• ๋ฉ”์„œ๋“œ

// ์ด๋™
let moved = win.shift(vec2(10.0, -5.0)); // ์ด๋™

// ํฌ๊ธฐ ์กฐ์ •
let scaled = win.scale(1.5);       // ๋น„์œจ๋กœ ์Šค์ผ€์ผ

// ์ •๋ ฌ
let aligned_top = Rect::from_x_y_w_h(
    other_rect.x(),
    win.top() - other_rect.h() * 0.5,
    other_rect.w(),
    other_rect.h()
);

// X์ถ•์œผ๋กœ ๋Š˜๋ฆฌ๊ธฐ
let stretched_x = Rect::from_x_y_w_h(
    win.x(),
    win.y(),
    win.w() * 2.0,
    win.h()
);

// ๋งคํ•‘ ์œ ํ‹ธ๋ฆฌํ‹ฐ
// (ํ˜„์žฌ ์ขŒํ‘œ, ์ •๊ทœํ™” 0.0, ์ •๊ทœํ™” 1.0, ํ™”๋ฉด ์™ผ์ชฝ ์ขŒํ‘œ, ํ™”๋ฉด ์˜ค๋ฅธ์ชฝ ์ขŒํ‘œ)
let x = map_range(0.5, 0.0, 1.0, win.left(), win.right());
// (ํ˜„์žฌ ์ขŒํ‘œ, ์ •๊ทœํ™” 0.0, ์ •๊ทœํ™” 1.0, ํ™”๋ฉด ์•„๋ž˜์ชฝ ์ขŒํ‘œ, ํ™”๋ฉด ์œ„์ชฝ ์ขŒํ‘œ)
let y = map_range(0.5, 0.0, 1.0, win.bottom(), win.top());

๐Ÿ”ธ ๋ถ„ํ•  ๋ฉ”์„œ๋“œ

// ๋น„์œจ ๊ธฐ๋ฐ˜ ๋ถ„ํ•  (0.0 ~ 1.0)
win.split_left(0.3)    // ์™ผ์ชฝ 30%
win.split_right(0.3)   // ์˜ค๋ฅธ์ชฝ 30%  
win.split_top(0.3)     // ์œ„์ชฝ 30%
win.split_bottom(0.3)  // ์•„๋ž˜์ชฝ 30%

// ์ ˆ๋ฐ˜ ๋ถ„ํ•  (ํŽธ์˜ ๋ฉ”์„œ๋“œ)
win.left_half()        // ์™ผ์ชฝ ์ ˆ๋ฐ˜ = split_left(0.5)
win.right_half()       // ์˜ค๋ฅธ์ชฝ ์ ˆ๋ฐ˜ = split_right(0.5)
win.top_half()         // ์œ„์ชฝ ์ ˆ๋ฐ˜ = split_top(0.5)
win.bottom_half()      // ์•„๋ž˜์ชฝ ์ ˆ๋ฐ˜ = split_bottom(0.5)

๐Ÿงฉ ์‹ค์ œ ์‚ฌ์šฉ ์˜ˆ์ œ

use nannou::prelude::*;

fn main() {
    nannou::sketch(view).size(800, 800).run();
}

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

    let quadrants = [
        Rect::from_corners(win.top_left(), win.xy()),
        Rect::from_corners(win.xy(), win.top_right()),
        Rect::from_corners(win.bottom_left(), win.xy()),
        Rect::from_corners(win.xy(), win.bottom_right()),
    ];
    
    // ์ƒ‰์ƒ ํŒ”๋ ˆํŠธ
    let colors = [
        hsla(220.0 / 360.0, 0.5, 0.1, 1.0),
        hsla(330.0 / 360.0, 0.5, 0.5, 1.0), 
        hsla(160.0 / 360.0, 0.5, 0.5, 1.0),
        hsla(270.0 / 360.0, 0.5, 0.5, 1.0), 
    ];
    
    // ์‚ฌ๋ถ„๋ฉด ๊ทธ๋ฆฌ๊ธฐ
    for (i, quadrant) in quadrants.iter().enumerate() {
        draw.rect()
            .xy(quadrant.xy())
            .wh(quadrant.wh())
            .color(colors[i]);
    }
    
    // ํ™”๋ฉด ์ค‘์•™์— ์ •์‚ฌ๊ฐํ˜•
    let square_size = win.w().min(win.h()) * 0.2;
    let square_rect = Rect::from_w_h(square_size, square_size);
    
    draw.rect()
        .xy(square_rect.xy())
        .wh(square_rect.wh())
        .color(WHITE);
        
    // === ๋ง‰๋Œ€ ๊ทธ๋ž˜ํ”„ ๋กœ์ง ์ˆ˜์ • ===
    let mouse_pos = app.mouse.position();
    
    // ๋ง‰๋Œ€๊ฐ€ ์‹œ์ž‘๋  ์™ผ์ชฝ x์ขŒํ‘œ๋ฅผ ๊ณ ์ •ํ•ฉ๋‹ˆ๋‹ค. (์—ฌ๋ฐฑ 0%)
    let start_x = win.left();
    let bar_h = 20.0;

    // ๋ง‰๋Œ€์˜ ๋„ˆ๋น„ = (๋งˆ์šฐ์Šค x์ขŒํ‘œ - ์‹œ์ž‘์  x์ขŒํ‘œ). ๋„ˆ๋น„๊ฐ€ ์Œ์ˆ˜๊ฐ€ ๋˜์ง€ ์•Š๋„๋ก clampํ•ฉ๋‹ˆ๋‹ค.
    let bar_w = (mouse_pos.x - start_x).max(0.0);

    // ๋ง‰๋Œ€์˜ ์ค‘์‹ฌ x์ขŒํ‘œ = ์‹œ์ž‘์  + (๊ณ„์‚ฐ๋œ ๋„ˆ๋น„ / 2)
    let bar_x = start_x + bar_w * 0.5;
    let bar_y = win.bottom() + bar_h * 0.5 + 10.0; // ํ™”๋ฉด ํ•˜๋‹จ์— ์•ฝ๊ฐ„์˜ ์—ฌ์œ  ๊ณต๊ฐ„ ์ถ”๊ฐ€

    draw.rect()
        .x_y(bar_x, bar_y)
        .w_h(bar_w, bar_h)
        .color(PURPLE);

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

๐Ÿ”ธ ์ฃผ์š” ์‚ฌํ•ญ

  • Rect์˜ ์ขŒํ‘œ๊ณ„๋Š” ์ค‘์‹ฌ์„ ์›์ (0,0) ์œผ๋กœ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค

  • left(), right(), top(), bottom()์€ ํ•ด๋‹น ๋ชจ์„œ๋ฆฌ์˜ ์ขŒํ‘œ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค

  • wh()๋Š” Vec2 ํƒ€์ž…์œผ๋กœ ๋„ˆ๋น„์™€ ๋†’์ด๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค

  • ์œˆ๋„์šฐ Rect๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ app.window_rect()๋กœ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค

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

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