Nannou 触ってみた
Nannou をさわってみた記事です
この記事は zztkm振り返りカレンダー Advent Calendar 2024 3 日目の記事です。
第3回はタイトルの通り入門してみた記事です、以前より興味を持っていた Nannou ですが Rust に慣れていないということもあり避けていました。 しかし最近では、Rust にも少し慣れてきたしチャレンジするなら今では?と思ったので今回入門してみました。
(振り返ってみたときにチャレンジしたかったことを思い出したのでやってみたので、振り返りカレンダーの記事であると言い張っています)
Nannou とは
An open-source creative-coding framework for Rust https://nannou.cc/
Rust の強みを creative-coding で活かそうというプロジェクトのようです。素晴らしいですね。
その他の creative-coding 言語やフレームワーク、ライブラリですと以下のようなものが挙げられます。
- Processing: https://processing.org/
- p5.js: https://p5js.org/
- py5: https://py5coding.org/index.html
- openFrameworks: https://openframeworks.cc/ja/
※ 他にもあるかもしれないけど自分が知っている範囲で書いてます
余談ですが筆者が初めて触れたプログラミング言語は Processing で、高専(後に入学するし)の夏休みのプログラミング教室的なものに参加したときにはじめて触ったと思います。
ちょっとだけコードを書いてみた
全然書けるようなことがないので、ちょっとコードを書いてみた。

use nannou::prelude::*;
fn hex_to_rgb(hex: &str) -> Option<Rgb<u8>> {
    if hex.starts_with('#') && hex.len() == 7 {
        let r = u8::from_str_radix(&hex[1..3], 16).ok()?;
        let g = u8::from_str_radix(&hex[3..5], 16).ok()?;
        let b = u8::from_str_radix(&hex[5..7], 16).ok()?;
        Some(Rgb::new(r, g, b))
    } else {
        None
    }
}
fn main() {
    nannou::app(model).update(update).run();
}
struct Model {
    points: Vec<Point2>,
}
fn model(app: &nannou::App) -> Model {
    app.new_window().size(600, 600).view(view).build().unwrap();
    let mut points = Vec::new();
    let num_points = 10_000; // 描画する点の数
    for _ in 0..num_points {
        let x = random_range(-300.0, 300.0);
        let y = random_range(-300.0, 300.0);
        points.push(pt2(x, y));
    }
    Model {
        points
    }
}
fn update(_app: &nannou::App, _model: &mut Model, _update: nannou::event::Update) {}
fn view(app: &nannou::App, model: &Model, frame: nannou::frame::Frame) {
    let draw = app.draw();
    // 背景を黒でクリア
    draw.background().color(nannou::color::BLACK);
    if let Some(color) = hex_to_rgb("#D9ED92") {
        let r = color.red as f32 / 255.0;
        let g = color.green as f32 / 255.0;
        let b = color.blue as f32 / 255.0;
        // 点を描画
        // TODO(zztkm): この点を毎回少しずつアップデートする処理を入れる
        for &point in &model.points {
            draw.ellipse()
                .x_y(point.x, point.y)
                .w_h(2.0, 2.0)
                .color(nannou::color::rgb(r, g, b));
        }
    }
    draw.to_frame(app, &frame).unwrap();
}
どこかで見た、update, draw スタイルのライフサイクルですね。
感想
- p5 とかと比べると情報が少ないので、参考にできるコードが少なく、自力でがんばる部分が増える(時間がかかるが悪いことではなくむしろ力になる
- Rust で書けるのは楽しいと思った
- これはコツコツ続けないと、良い作品を書けないと感じたので、今回書いたコードを改善しつつちょっとずつやってみようと思う。