[Processing]なぞって描くインタラクティブアート

#過去作品の応用ですが
[[Processing]クリック点を保存してアート作品を描く](https://qiita.com/NekoCan/items/f628be98779451751f19)
これの応用？もっと遊びやすく、単純にしたものです
（文化祭での展示用に簡単にしたもの）

収束点を中心に固定し、なぞるだけで点が打てるようにしました

#実行結果
[OpenProcessing](https://openprocessing.org/sketch/741689)にアップロードしました

![Veil.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/554244/d3805ca9-9e1d-2211-ab84-6b2257abfc2a.gif)

#プログラム
拡張子本当は.pdeですけど、javaにした方が色ついて見やすいかなって

```Veil.java
import controlP5.*;
Vertex head;
Vertex tale;
Vertex prev;
float timer = 0;
float num;
Boolean randomBool = false;

void setup() {
  size(1800, 800, P2D);
  //size(1800, 800);
  frameRate(30);
  colorMode(HSB, 1);
  noStroke();
  keyPressed();

  ControlP5 cp = new ControlP5(this);
  cp.addButton("Reset")
    .setSize(width/5*2, height/20)
    .setPosition(width/10*3, height-height/20);

  cp.addToggle("Random")
    .setLabel("Random")
    .setSize(width/10, height/20)
    .setPosition(width-width/100*15, height-height/20);
}

void draw() {
  background(1);

  prev = head;
  beginShape(TRIANGLE_FAN);
  do {
    prev.Draw();
    prev = prev.next;
  } while (prev != null);
  endShape();

  if (mousePressed) {
    if (millis()/1000f < timer + 0.05f) return;
    timer = millis()/1000;
    tale = tale.next = new Vertex((int)mouseX, (int)mouseY, tale);
  }
}

class Vertex {
  Vertex next;
  Vertex prev;
  float x, y;
  float prevX, prevY;
  color c;

  Vertex(float X, float Y, Vertex Prev) {
    x = X;
    y = Y;
    prev = Prev;
    if (prev != null) {
      prevX = (prev != head ? prev.x : tale.x);
      prevY = (prev != head ? prev.y : tale.y);
    }
    if (randomBool) c = color(random(1), 1, 1, 0.4);
    else c = color(num-=0.01, 1, 1, 0.4);
    if (num <= 0) num = 1;
  }

  void Draw() {
    fill(c);
    vertex(x, y);

    if (prev == null) return; 
    float X = prevX-x;
    float Y = prevY-y;
    x += ( X > 0 ? 1 : (X == 0 ? 0 : -1));
    y += ( Y > 0 ? 1 : (Y == 0 ? 0 : -1));
    if (X + Y != 0) return ;
    if (prev != head) {
      prevX = prev.x;
      prevY = prev.y;
    } else {
      head.next = null;
      if (next != null) {
        next.prev = null;
        next.prev = head;
        head.next = next;
        head.next.prevX = head.x;
        head.next.prevY = head.y;
      } else {
        tale = head;
      }
    }
  }// Draw end }
} // class Vertex end }

void keyPressed() {
  head = new Vertex(width/2, height/2, null);
  tale = head;
  randomSeed(millis());
}

void Reset() {
  keyPressed();
}

//GUIイベントハンドラ
void controlEvent(ControlEvent theEvent) {
  timer += 0.5;
  switch(theEvent.getController().getName()) {
  case "Random":
    randomBool = !randomBool;
    break;
  }
}

```
#アンドロイド版
![Kikagaku.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/554244/6d4c7bf5-ab5b-7221-9192-a6a8693e10b3.gif)

#アンドロイド用のプログラム
```Veil.java
import controlP5.*;
import android.util.*;

public static final String TAG = "AM-MOUSE";

//http://mslabo.sakura.ne.jp/WordPress/make/processing%E3%80%80逆引きリファレンス/タップを検知するには%EF%BC%88androidmode編%EF%BC%89/

PImage image ;
int     touchCount;  //タッチ数
float timer = 0;
Veiler veiler;
TouchEvent touchEvent;

//11 = TRIANGLE_FAN
//18 = QUAD_STRIP
int mode = 11;

void setup() {
  fullScreen();
  noStroke();
  frameRate(30);
  colorMode(HSB, 1);
  veiler = new Veiler();

  ControlP5 cp = new ControlP5(this);

  cp.addButton("Reset")
    .setSize(width/5*2, height/20)
    .setPosition(width/10*3, height-height/20);

  //現在のタッチ数を初期化
  touchCount = 0;
  
  image = loadImage("Kihanagaku.png");
  imageMode(CENTER);
}

void draw() {
  background(1, 1);
  
  veiler.Draw();
  
  if(veiler.tale == veiler.head){
    image(image,width/2,height/2);
  }
  
  if (touchCount > 0) {
    Drawer(touchEvent);
  }
}

public void touchStarted(TouchEvent touchEvent) {
  //タッチされている数を加算
  touchCount++;
  this.touchEvent = touchEvent;
  Drawer(touchEvent);
}

public void touchMoved(TouchEvent te) {
  touchEvent = te;
}

public void touchEnded(TouchEvent touchEvent) {
  //タッチされている数を減算
  touchCount = touchCount - 1;

  //0が渡されたらすべての指が離れたと考える
  if ( touchEvent.getNumPointers() == 0 ) {
    touchCount = 0;
  }
}

void Drawer(TouchEvent te) {
  if (millis()/1000f < timer + 0.1f) return;
  timer = millis()/1000f;
  int num = te.getNumPointers();
  for (int i=0; i<num; i++) {
    veiler.add((int)te.getPointer(i).x, (int)te.getPointer(i).y);
  }
}

class Veiler {

  Vertex head;
  Vertex tale;
  Vertex prev;
  float num;//色に使用

  Veiler() {
    Reset();
  }

  void Reset() {
    head = new Vertex(width/2, height/2, null);
    tale = head;
    randomSeed(millis());
    num = 10;
  }

  void add(float x, float y) {
    tale = tale.next = new Vertex(x, y, tale);
  }

  void Draw() {
    prev = head;
    beginShape(mode);
    do {
      prev.Draw();
      prev = prev.next;
    } while (prev != null);
    endShape();
  }

  class Vertex {
    Vertex next;
    Vertex prev;
    float x, y, X, Y;
    float prevX, prevY;
    color c;

    Vertex(float X, float Y, Vertex Prev) {
      x = X;
      y = Y;
      prev = Prev;
      if (prev != null) {
        prevX = (prev != head ? prev.x : tale.x);
        prevY = (prev != head ? prev.y : tale.y);
      }
      c = color((num -= 0.002)%1, 1, 1, 0.4f);
      if (num <= 0)num = 10;
    }

    void Draw() {
      fill(c);
      vertex(x, y);

      if (prev == null) return ;
      X = prevX-x;//一つ前のノードから自分の位置を
      Y = prevY-y;//引いて移動方向を算出
      x += ( X > 0 ? 1 : (X == 0 ? 0 : -1));
      y += ( Y > 0 ? 1 : (Y == 0 ? 0 : -1));
      
      if (X + Y != 0) return;
      
      //先頭に追いついたら
      if (prev != head) {
        prevX = prev.x;
        prevY = prev.y;
      } else {
        head.next = null;//先頭から2個目を削除
        if (next != null) {
          next.prev = null;
          next.prev = head;
          head.next = next;
          head.next.prevX = head.x;
          head.next.prevY = head.y;
        } else { //全消し
          tale = head;
        }
      }
      
    }// Draw end }
  } // class Vertex end }
}

void Reset() {
  veiler.Reset();
}
```
コメントにも入ってますが[参考文献](http://mslabo.sakura.ne.jp/WordPress/make/processing%E3%80%80逆引きリファレンス/タップを検知するには%EF%BC%88androidmode編%EF%BC%89/)

なにも描かれていない時に表示される画像（Kihanagaku.png）はこれです
![Kihanagaku.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/554244/986e70d6-5fe3-6459-9465-b5ee5ebf2d20.png)

#以上　幾華学　でした
前回作
[[Processing]クリック点を保存してアート作品を描く](https://qiita.com/NekoCan/items/f628be98779451751f19)