p5.jsとフェイストラッカー（clmtracker）で顔面ブロック崩し

授業で作った 忘備録
動画載せたツイート：[p5jsほぼはじめましてですが目線ブロック崩しを作りました全然クリアできん](https://twitter.com/okashitabetainn/status/1271405915854401536?s=20)
参考にしたサイト：[Processingでブロック崩しを作ったよ！！！！！](https://qiita.com/minami_o/items/f96fe5190f6ed9ba0299)（大変お世話になりました）
p5.jsライブラリ：[clmtrackr(GitHub)](https://github.com/auduno/clmtrackr)

コードが汚いなあ！提出することで一杯いっぱいだった

```sketch.js
var capture;
var tracker;
var w = 640;
var h = 480;

var block = [];
var index = 8; //行数
var blockrgb;
var blockcolor = [];
var none;
var block_w = 79;
var block_h = 23;
var block_x = [];
var block_y = [];

var ball_x = 150;
var ball_y = 140;
var ball_d = 12;
var vx = 3;
var vy = -5;

var bar_x = 200;
var bar_y = 400;
var bar_width = 60;
var bar_height = 25;

var click = false;
var score = 0;

var text_x = bar_x - 50;
var text_y = bar_y - 50;

var mouth_openness;
var mouth_width;

var mode;

function setup() {
  capture = createCapture({
    audio: false,
    video: {
      width: w,
      height: h
    }
  }, function() {
    console.log('capture ready.')
  });

  capture.elt.setAttribute('playsinline', '');
  createCanvas(w, h);
  capture.size(w, h);
  capture.hide();

  tracker = new clm.tracker();
  tracker.init();
  tracker.start(capture.elt);

  noStroke();
  index = 10;
  blockrgb = color(255, 224, 102);
  none = color(0, 0, 0, 0);
  for (let j = 0; j < 4; j++) {
    for (let i = 0; i < index; i++) {
      var k = j * index + i + 1;
      blockcolor[k] = blockrgb;
      block[k] = new Block(i * 80, j * 24, block_w, block_h, blockcolor[k]);
      block_x[k] = i * 80;
      block_y[k] = j * 24;
    }
  }
  mode = 0;
}

function draw() {
  background(100, 20);
  push();
  translate(width, 0);
  scale(-1, 1);
  image(capture, 0, 0, w, h);
  var positions = tracker.getCurrentPosition();

  let outline = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14];
  let left_eyebrow = [15, 16, 17, 18];
  let right_eyebrow = [19, 20, 21, 22];
  let left_eye = [28, 67, 29, 68, 30, 69, 31, 70];
  let right_eye = [23, 63, 24, 64, 25, 65, 26, 66];
  let nose_height = [33, 41, 62];
  let nose = [34, 35, 36, 42, 37, 43, 38, 39, 40];
  let mouth_outer = [44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55];
  let mouth_inner = [44, 61, 60, 59, 50, 58, 57, 56];


  // Check https://github.com/auduno/clmtrackr

  for (let j = 0; j < 4; j++) {
    for (let i = 0; i < index; i++) {
      block[j * index + i + 1].draw();
    }
  }


  fill(112, 193, 179);
  ellipse(ball_x, ball_y, ball_d, ball_d);

  if (click) {
    ball_x += vx;
    ball_y += vy;
  }

  if (ball_x > width || ball_x < 0) {
    vx *= -1;
  }
  if (ball_y < 0) {
    vy *= -1;
  }


  if (ball_x > bar_x - 12 && ball_x < bar_x + bar_width + 12) {
    if (ball_y > bar_y && ball_y < bar_y + 12) {
      vx += random(1, 1);
      vy *= -1.01;
    }
  }

  for (let j = 0; j < 4; j++) {
    for (let i = 0; i < index; i++) {
      var k = j * index + i + 1;
      if (blockcolor[k] == blockrgb) {
        if (ball_y > block_y[k] && ball_y < block_y[k] + block_h) {
          if (ball_x > block_x[k] && ball_x < block_x[k] + block_w) {
            vy *= -1;
            blockcolor[k] = none;
            score += 10;
          }
        }
        if (ball_x== block_x[k] || ball_x == block_x[k] + block_w) {
          if (ball_y  > block_y[k] && ball_y < block_y[k] + block_h) {
            vx *= -1;
            blockcolor[k] = none;
            score += 10;
          }
        }
      }
      block[k] = new Block(i * 80, j * 24, block_w, block_h, blockcolor[k]);
    }
  }


  if (positions.length == 71) {
    bar_x = positions[23][0] - 15;
    bar_y = (positions[23][1] + positions[28][1]) / 2 - bar_height / 2;
    bar_width = positions[28][0] - positions[23][0] + 30;
    fill(10, 11, 9);
    bar_height = bar_width / 4;
    rect(bar_x, bar_y, bar_width, bar_height);

    if (bar_x > width - bar_width) {
      bar_x = width - bar_width;
    }
    if (bar_x < 0) {
      bar_x = 0;
    }
    mouth_openness = dist(positions[60][0], positions[60][1],
      positions[57][0], positions[57][1]);
    mouth_openness = mouth_openness / bar_width;
    mouth_width = dist(positions[44][0], positions[44][1],
      positions[50][0], positions[50][1]);
    mouth_width = mouth_width / bar_width;
    //console.log(mouth_width);

  }
  if (!click) {
    pop();
    textSize(48);
    textAlign(CENTER, CENTER);
    strokeWeight(1);
    stroke(112, 193, 179);
    fill(255, 100);
    text("クリックでスタート", width / 2, height / 2);
    noStroke();
    translate(width, 0);
    scale(-1, 1);
  }
  if (ball_y > height) {
    mode = 1;
    pop();
    textSize(bar_height / 2 - 5);
    text_x = width - bar_x - bar_width / 2;
    text_y = bar_y;
    noFill();
    strokeWeight(1);
    stroke(242, 95, 92);
    textAlign(CENTER, TOP);
    text("Game Over", text_x, text_y + 2);
    textAlign(CENTER, BOTTOM);
    text("Your Score : " + score, text_x, text_y + bar_height - 2);
    textSize(48);
    textAlign(CENTER, CENTER);
    fill(255, 100);
    text("口を大きく開けてリセット", width / 2, height / 2);
    noStroke();
    translate(width, 0);
    scale(-1, 1);
    if (mouth_openness >= 0.2 && mouth_width >= 0.5) {
      changeMode();
    }
  }
}

function mousePressed() {
  if (mode == 0) {
    click = !click;
  }
}

function changeMode() {
  mode = 0;
  score = 0;
  ball_x = random(150, width - 150);
  ball_y = 140;
  vx = 3;
  vy = -5;
  click = false;
  for (let j = 0; j < 4; j++) {
    for (let i = 0; i < index; i++) {
      var k = j * index + i + 1;
      blockcolor[k] = blockrgb;
      block[k] = new Block(i * 80, j * 24, block_w, block_h, blockcolor[k]);
    }
  }
}

class Block {
  constructor(_x, _y, _w, _h, _rgb) {
    noStroke();
    this.x = _x;
    this.y = _y;
    this.w = _w;
    this.h = _h;
    this.rgb = _rgb;
  }

  draw() {
    fill(this.rgb);
    rect(this.x, this.y, this.w, this.h);
  }
}
```

あとはhtmlの方に使うライブラリ書く