rust nannouで一次元セルオートマトンのカラー化

nannou

前回、rust nannouで1次元セルオートマトンを描くでRule90でセルオートマトンを描くっていうプログラムをしました。

今回は、それをカラー化してみましょう。

今回のソースコードの変更点は次の通り

  1. カラー化(hslでカラーを設定)
  2. モデルを配列からベクタにする
  3. 初期値をランダムにする

こんな感じでやってます。

では、変更含め見ていきましょう

前回のおさらい

前回の記事(rust nannouで1次元セルオートマトンを描く)を見てもらえると、ソースコードは載ってますが、おおざっぱに言うと

要素100個の配列を準備して、現在の状態から更新した状態を作って、っていうのを繰り返すコードになってます。

前回のまとめで、初期値をランダムにしたりカラーにしたらどう?っていう話をしたので、今回はそれを実装します。

一次元セルオートマトンのランダム&カラー化の手順

では、初期値のランダム、カラー化やっていきましょう。手順を順番に進めていきます。

カラー化をする

カラー化は、描画の部分に手を加えていきます。

for i in 0..model.life_1.len() {
        if model.life_1[i] == 1 {
            draw.rect()
                .w_h(5.0, 5.0)
                .x((i as f32) * 5.0 - 200.0)
                .y(-5.0 * (f as f32) + 300.0)
                .hsl((f as f32).sin(), 1.0, 0.5);
        }
    }

これが、加えた結果です。

最後の行に

.hsl((f as f32).sin(), 1.0, 0.5);

この1行を加えただけです。

カラーの表現方法っていうのはいくつかあります。rgbやhsl,hsv,hwb,カラーネームを指定する方法など、alphaを入れるとか入れないとか、いくつかあります。

今回はhslで指定してます。やり方は色々です。フレーム数を三角関数にぶっこんで、値変換するみたいなコードにしてます。

モデルを配列からベクタにする

この後、2,3で何するかっていうと、初期値をランダムにしていきたいんです。配列のまま、やっていってもいいんですが、今後の拡張性とか、作りやすさのために配列をベクタにします。

今までは

struct Model {
    life_1: [u8; 100],
    life_2: [u8; 100],
}

こんな感じで、配列で表現してました。

配列だと、要素の数を最初に定義したり、要素数に自由度がない。初期値を初期化するときにイテレーターを使いたい(配列でも使えるのかな?)ってのがあって、ベクタにします。

ベクタにするのはそんなに難しいことじゃないです。とっても簡単

struct Model {
    life_1: Vec<u8>,
    life_2: Vec<u8>,
}

これだけ、かたちはVecで、要素は<u8>ですよとしてあげればOK。超簡単

次にこれに合わせて、初期値の初期化、ランダムな初期値の代入をやっていきましょう

初期値をランダムにする

ランダムな数を入れる方法はいくつかあるんですが、例えば配列であれば、forまわして、ランダムな値を入れていく感じです。

今回は、せっかくvecにしたので、イテレーターを使って、mapを使ってやってみましょう。ベクタにしてイテレーター使うのは、先述の通り、要素の数の自由度が増すっていうのも一つです。

初期化のコードはこんな感じです。

let max_cell = 1000;
let life_1 = (0..max_cell)
    .map(|_| {
        if nannou::rand::random_range(0.0, 1.0) < 0.5 {
           0
        } else {
            1
        }
    })
    .collect();
let life_2 = (0..max_cell).map(|_| 0).collect();
Model { life_1, life_2 }

ランダムの生成方法が微妙だけど(笑)まぁいいや

life_1について、mapで中身は、ランダム0から1までのランダムな数を定義して、0.5未満だったら0、それ以外なら1を返す、それをゼロからmax_cellまでやって、コレクトしてlife_1に入れてよ。っていう構造です。

僕あんまり、イテレーター得意じゃなくて、練習のためにやりたいなと思ってて今回はそれにしてみました。

life_2ははゼロで埋め尽くす。っていうコードです。fill()っていう関数があるんだけど、うまく使えなくて、今回はmapでやりました。fill使えたらカッコよかったな。。

これで、初期値(life_1)にランダムの数をバッファであるlife_2を初期化できました。

このベクタにした都合上です。update関数の中の

model.life_1 = model.life_2;

っていう代入式が配列のころは、許されてたんですが、これが許されなくなったので

model.life_1 = model.life_2.clone();

っていう風に書き換えました。

まとめ

今回は、初期値をランダムにして、カラー化するっていうのをやりました。その中で、配列からベクタにしました。ベクタにするとmax_cellっていう変数を新たに作って、セルの数を自由に設定できるようにもしました。

配列でやってもいいけど、ベクタだとスライスもできるし、自由度が増すかな?と思います。それぞれ使いどころだと思うけどね。

色んなやり方で、実装できるので、配列でどうしてもやりたい!っていうのではれば、それでやってみてもいいと思います。

それぞれ、やり方はいっぱいありますので、是非チャレンジをしてみましょう

ではまた!

コメント

タイトルとURLをコピーしました