https://docs.google.com/presentation/d/1Z6SidOzB32I8VX1bTrDZAUZKZ5KchGT1NTqVsnP7EiE/edit?usp=sharing

let video;
let poseNet;
let poses = [];
let points = [];
let pacMan;
let score = 0;
let timer = 30; 
let intervalID;
let startSound;
let gameStarted = false; 

function preload() {
  startSound = loadSound('/mnt/data/pacman_beginning.wav');
}

function setup() {
  createCanvas(640, 480);

  video = createCapture(VIDEO);
  video.size(640, 480);
  video.hide();

  poseNet = ml5.poseNet(video, modelReady);
  poseNet.on('pose', function(results) {
    poses = results;
  });

  for (let i = 0; i < 5; i++) {
    points.push(new Dot(random(width), random(height)));
  }

  pacMan = new PacMan();

  startSound.play();
  setTimeout(() => {
    gameStarted = true; 
    intervalID = setInterval(() => {
      if (timer > 0) {
        timer--;
      }
    }, 1000);
  }, 3000); 
}

function modelReady() {
  console.log('PoseNet model ready!');
}

function draw() {
  background(220);

  image(video, 0, 0, width, height);

  if (!gameStarted) {

    textSize(32);
    fill(255, 0, 0);
    textAlign(CENTER, CENTER);
    text('Stand Up', width / 2, height / 2);
    return; 
  }

  pacMan.update();
  pacMan.display();

  for (let i = points.length - 1; i >= 0; i--) {
    points[i].display();
    if (pacMan.eats(points[i])) {
      points.splice(i, 1);
      score++;
    }
  }

  textSize(24);
  fill(0);
  text(`Score: ${score}`, 10, 25);
  text(`Time: ${timer}`, 10, 50);
  
  if (timer <= 0) {
    gameOver();
  }
}

function gameOver() {
  noLoop(); 
  textSize(32);
  fill(255, 0, 0);
  textAlign(CENTER, CENTER);
  text('Game Over!', width / 2, height / 2);
  clearInterval(intervalID); 
}

class PacMan {
  constructor() {
    this.x = width / 2;
    this.y = height / 2;
    this.size = 50;
  }

  update() {

    if (poses.length > 0) {
      let keypoints = poses[0].pose.keypoints;
      let leftShoulder = keypoints.find(point => point.part === 'leftShoulder');
      let rightShoulder = keypoints.find(point => point.part === 'rightShoulder');
      
      if (leftShoulder && rightShoulder && leftShoulder.score > 0.2 && rightShoulder.score > 0.2) {

        this.x = (leftShoulder.position.x + rightShoulder.position.x) / 2;
        this.y = (leftShoulder.position.y + rightShoulder.position.y) / 2;
      }
    }
  }

  display() {
    noStroke(); 
    fill(255, 255, 0);
    arc(this.x, this.y, this.size, this.size, PI / 4, -PI / 4); 
  }

  eats(dot) {
    let d = dist(this.x, this.y, dot.x, dot.y);
    return d < this.size / 2 + dot.size / 2;
  }
}

class Dot {
  constructor(x, y) {
    this.x = x;
    this.y = y;
    this.size = 20;
  }

  display() {
    noStroke(); 
    fill(255, 0, 0);
    ellipse(this.x, this.y, this.size);
  }
}

https://editor.p5js.org/yh4069/sketches/UO931d5uC

https://editor.p5js.org/yh4069/sketches/SXvl6W7sL