AI Piano:

https://experiments.withgoogle.com/ai/ai-duet/view/

AI Duet primarily uses Recurrent Neural Networks (RNNs), specifically Long Short-Term Memory (LSTM) networks. The model was trained by a large number of MIDI files. These MIDI files encode music in a format that specifies the pitch, intensity, and duration of each note played. LSTMs are particularly well-suited for tasks that involve predictions based on time series data, which is a natural fit for music to create notes after the user input their notes.

Destory It! v2:

I changed the wrist position into index finger position this week.

10月3日.mov

https://editor.p5js.org/YuhongSun/sketches/K3qdQEiXl

let handPose;
let video;
let hands = [];
let squares = [];
let score = 0;
let gameTimer = 30;
let gameActive = false;
let numSquares = 5;

function preload() {
  handPose = ml5.handPose();
}

function setup() {
  createCanvas(640, 480);
  video = createCapture(VIDEO);
  video.size(640, 480);
  video.hide();
  handPose.detectStart(video, gotHands);
  resetGame();
}

function draw() {
  background(0);
  image(video, 0, 0, width, height);

  if (gameActive) {
    updateGame();
    displayScoreAndTime();
  }

  if (gameTimer <= 0) {
    displayFinalScore();
    gameActive = false; 
  }
}

function resetGame() {
  squares = createRandomSquares(numSquares);
  score = 0;
  gameTimer = 30;
  gameActive = true;
  loop();
}

function updateGame() {
  drawSquares();
  if (hands.length > 0) {
    for (let i = 0; i < hands.length; i++) {
      let hand = hands[i];
      drawHandCircles(hand);
      checkCollision(hand);
    }
  }
  
  if (squares.length === 0) {
    squares = createRandomSquares(numSquares);
  }
}

function drawSquares() {
  fill(0, 255, 0);
  noStroke();
  squares.forEach(square => {
    rect(square.x, square.y, square.size, square.size);
  });
}

function drawHandCircles(hand) {
  let indexTip = hand.keypoints[8];
  fill(255, 0, 0); 
  noStroke();
  if (indexTip) circle(indexTip.x, indexTip.y, 20);
}

function checkCollision(hand) {
  let indexTip = hand.keypoints[8];

  squares = squares.filter(square => {
    if (isPointInSquare(indexTip, square)) {
      score++;
      return false;
    }
    return true;
  });
}

function isPointInSquare(point, square) {
  return point.x > square.x && point.x < square.x + square.size &&
         point.y > square.y && point.y < square.y + square.size;
}

function createRandomSquares(num) {
  let newSquares = [];
  for (let i = 0; i < num; i++) {
    let size = random(20, 50);
    newSquares.push({
      x: random(0, width - size),
      y: random(0, height - size),
      size: size
    });
  }
  return newSquares;
}

function displayScoreAndTime() {
  fill(255);
  textSize(24);
  textStyle(BOLD);
  text(`Score: ${score}`, 30, 40);
  text(`Time Left: ${gameTimer}`, 30, 70);
  if (frameCount % 60 == 0 && gameTimer > 0) {
    gameTimer--;
  }
}

function displayFinalScore() {
  fill(255);
  textSize(64);
  textStyle(BOLD);
  textAlign(CENTER);
  text(`Your Score: ${score}`, width / 2, height / 2 + 30);
}

function mousePressed() {
  if (!gameActive || gameTimer <= 0) {
    resetGame();
  }
}

function gotHands(results) {
  hands = results;
}