xxxxxxxxxx
194
let mobilenet;
let predictor;
let video;
let value = 0;
let slider;
let addButton;
let trainButton;
let playAgainButton;
let ballSize;
let ballX;
let ballY;
let gate;
let trainingReady = false;
let playBall = false;
let gatePassCount;
let gateCountText;
let crashed = false;
let leftGateEdge;
let rightGateEdge;
let topGate;
let bottomGate;
function modelReady() {
console.log("Model is ready!!!");
}
function videoReady() {
console.log("Video is ready!!!");
}
function whileTraining(loss) {
if (loss == null) {
console.log("Training Complete");
predictor.predict(gotResults);
trainingReady = true;
slider.remove();
addButton.remove();
trainButton.remove();
playBall = true;
} else {
console.log(loss);
trainingReady = false;
}
}
function gotResults(error, result) {
if (error) {
console.error(error);
} else {
// updated to work with newer version of ml5
// value = result;
value = result.value;
predictor.predict(gotResults);
}
}
class obsGate {
constructor(barX) {
this.x = barX;
this.gateWidth = width / 2;
this.y = 0;
this.height = 40;
this.speed = 1;
}
build() {
noStroke();
fill(10, 10, 10);
rectMode(CORNERS);
fill(255, 125, 0);
leftGateEdge = this.x - this.gateWidth / 2;
if (leftGateEdge < 0) {
leftGateEdge = 0;
}
rightGateEdge = this.x + this.gateWidth / 2;
if (rightGateEdge > width) {
rightGateEdge = width;
}
bottomGate = this.y + this.height;
topGate = this.y ;
rect(0, topGate, leftGateEdge, bottomGate);
rect(rightGateEdge, topGate, width, bottomGate);
}
fall() {
this.y += this.speed;
if (this.y > height) {
this.y = 0;
this.gateWidth = random(ballSize + 30, width / 2 + 30);
this.x = width / 2 + random(-width / 3, width / 3);
gatePassCount--;
}
}
check() {
if (bottomGate > ballY - ballSize / 2 && topGate < ballY + ballSize / 2) {
if (
leftGateEdge > ballX - ballSize / 2 ||
rightGateEdge < ballX + ballSize / 2
) {
playBall = false;
crashed = true;
playAgain();
}
}
if (gatePassCount < 1) {
playBall = false;
playAgain();
}
}
}
function setup() {
createCanvas(400, 660);
ballSize = width / 8;
ballY = (height * 7) / 10;
gate = new obsGate(width / 2);
gatePassCount = 5;
video = createCapture(VIDEO, { flipped: true });
video.hide();
background(0);
mobilenet = ml5.featureExtractor("MobileNet", modelReady, { flipped: true });
predictor = mobilenet.regression(video, videoReady);
slider = createSlider(0, 1, 0.5, 0.01);
addButton = createButton("Add L/R ctrl image");
addButton.mousePressed(function () {
predictor.addImage(slider.value());
});
trainButton = createButton("train");
trainButton.mousePressed(function () {
predictor.train(whileTraining);
});
}
function playAgain() {
if (trainingReady && !playBall) {
playAgainButton = createButton("Play Again?");
playAgainButton.position(width / 2 - 100, height / 2 + 30);
playAgainButton.size(200);
playAgainButton.mousePressed(function () {
playBall = true;
gatePassCount = 5;
gate.y = 0;
crashed = false;
playAgainButton.remove();
});
}
}
function draw() {
background(0);
image(video, 0, 0, width, height);
noStroke();
fill(255);
textSize(16);
text(nf(value, 1, 3), 20, height - 10);
gateCountText = "Gates to pass: " + gatePassCount;
text(gateCountText, width - 150, height - 10);
if (trainingReady) {
if (playBall) {
rectMode(CENTER);
strokeWeight(5);
stroke(255, 0, 200);
noFill();
ballX = value * width;
circle(ballX, ballY, ballSize);
noStroke();
fill(255);
gate.build();
gate.fall();
gate.check();
} else {
if (crashed) {
fill(255, 0, 0);
textSize(50);
textAlign(CENTER);
text("CRASHED", width / 2, height / 2);
} else {
fill(0, 255, 0);
textSize(50);
textAlign(CENTER);
text("WELL DONE", width / 2, height / 2);
}
}
} else {
textSize(30);
textAlign(CENTER);
text("Train your machine", width / 2, height / 2);
text("along with the slide bar", width / 2, height / 2 + 30);
}
}