メディアアート~インクスロー~

## 作品名: インクスロー
この作品は画面をクリックすると、インク球を投げたスプラッシュがいっぱい出てきます:art:

以下のような作品が仕上がります。

動画
<iframe width="560" height="315" src="https://www.youtube.com/embed/3qZgf8-J3Tk?si=f_MZ0TAaQQq1yTGW" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>


スクリーンショット
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1226429/eb05f86d-defa-405a-851e-bbdd1cc17bcf.png" width="60%"><br>

前回のアートと同じく色相をランダムに設定することでできて、いろんな色のインクスローできます。

## プログラム

まず、インクの配列(Splash)と色の準備をします。

```
int MaxColor;

float Hue = 0; // 色相
float Saturation = 500; // 彩度
float Value = 1000; // 明度

ArrayList<Splash> splashes = new ArrayList<Splash>();

```

次、初期設定を行います。
backgroundを白にするため、MaxColor-1と設定し、スクリーンサイズは大きくします。

```
void setup() {
  size(1600, 1200);
  MaxColor = 400;
  colorMode(HSB, MaxColor, 255, 255); // HSB + 透明度対応
  background(MaxColor-1);
}

```

インクを定義するため、Splashクラスを作ります。
アルゴリズムは以下の通りです。
<ol>
<li>初期のポジション(マウスクリックした場所)を設定し、さらに中心のインクの周囲に小さいインクが散らばるようにそれぞれ半径とsin,cosを掛け合わせて平行移動をさせる
<li>周囲のインクの大きさをランダムに設定する
</ol>


```
class Splash {
    float x, y;
    float Size;
    float splash_hue;
    float[] diff_x = new float[10]; // 10個の円のX座標オフセット
    float[] diff_y = new float[10]; // 10個の円のY座標オフセット
    float[] size = new float[10];   // 10個の円のサイズ
    float angle; 

    Splash(float startX, float startY, float hue) {
        x = startX;
        y = startY;
        splash_hue = hue;
        for (int i = 0; i<10; i++){
            angle = random(0,360);
            diff_x[i] = x + 150*cos(radians(angle));
            diff_y[i] = y + 150*sin(radians(angle));
            size[i] = random(100, 200);
        }
    }
    
    void display() {
    noStroke();
    fill(splash_hue, Saturation, Value, 220); // アルファ値を適用
    
    for (int i = 0; i<10; i++){
        ellipse(diff_x[i], diff_y[i], size[i], size[i]);
    }
    ellipse(x, y, 300, 300);
  }
  
}

```



さらに、上記の動画と画像のようにスクリーンショットを行います。
スクリーンショットでは、keyPressed()を使ってキーボード処理を受け取ります。

```
void keyPressed() {
    //画像を作成
    if(key == 's'){
        PImage img = createImage(width, height, RGB);
     
        //画面を画像にコピー
        loadPixels();
        img.pixels = pixels;
        img.updatePixels();
         
        //画像のピクセル情報を切り出して保存
        img = img.get(0, 0, width, height);
        img.save("drawing.png");
    }
}

```
最後、描画時の処理とマウス処理を行います。
マウスがクリックされたら、クリックした位置でインクスローを行い、インクをばらまきます。
また、draw()と言われる継続的に行う関数でfor文を使ってインクスローのアニメーションを行います。

```
void draw() {
  background(MaxColor-1); // 背景を描画してリフレッシュ
  
  // 全ての粒子を更新・描画
  for (int i = 0; i <= splashes.size() - 1; i++) {
    Splash s = splashes.get(i);
    s.display();
    
  }
  
}

void mousePressed() {
  Hue = random(0, 400);     
  splashes.add(new Splash(mouseX, mouseY, Hue));
}

```

コード全体は以下の通りです。

```
int MaxColor;

float Hue = 0; // 色相
float Saturation = 500; // 彩度
float Value = 1000; // 明度

ArrayList<Splash> splashes = new ArrayList<Splash>();

void setup() {
  size(1600, 1200);
  MaxColor = 400;
  colorMode(HSB, MaxColor, 255, 255); // HSB + 透明度対応
  background(MaxColor-1);
}

void draw() {
  background(MaxColor-1); // 背景を描画してリフレッシュ
  
  // 全ての粒子を更新・描画
  for (int i = 0; i <= splashes.size() - 1; i++) {
    Splash s = splashes.get(i);
    s.display();
    
  }
  
}

void mousePressed() {
  Hue = random(0, 400);     
  splashes.add(new Splash(mouseX, mouseY, Hue));
}

void keyPressed() {
    //画像を作成
    if(key == 's'){
        PImage img = createImage(width, height, RGB);
     
        //画面を画像にコピー
        loadPixels();
        img.pixels = pixels;
        img.updatePixels();
         
        //画像のピクセル情報を切り出して保存
        img = img.get(0, 0, width, height);
        img.save("drawing.png");
    }
}

class Splash {
    float x, y;
    float Size;
    float splash_hue;
    float[] diff_x = new float[10]; // 10個の円のX座標オフセット
    float[] diff_y = new float[10]; // 10個の円のY座標オフセット
    float[] size = new float[10];   // 10個の円のサイズ
    float angle; 

    Splash(float startX, float startY, float hue) {
        x = startX;
        y = startY;
        splash_hue = hue;
        for (int i = 0; i<10; i++){
            angle = random(0,360);
            diff_x[i] = x + 150*cos(radians(angle));
            diff_y[i] = y + 150*sin(radians(angle));
            size[i] = random(100, 200);
        }
    }
    
    void display() {
    noStroke();
    fill(splash_hue, Saturation, Value, 220); // アルファ値を適用
    
    for (int i = 0; i<10; i++){
        ellipse(diff_x[i], diff_y[i], size[i], size[i]);
    }
    ellipse(x, y, 300, 300);
  }
  
}
```

マウスでクリックするとparticleや図形表示することができ、インタラクティブアート作成ができます！

## まとめ
今回の作品では、画面をクリックしてランダムな色でインクを投げることができます。
さらに今後は、この作品とOpenCVでナワバリバトルを行うと面白味が増えると考えられます。