Code viewer for World: Aim training (by Antoine K...
// needs mouse drag before anything happens 
//choose settings

const maxBalls = 10; //number of targets
let chosenTime = 20; //game duration (in seconds)
//Change the radius at ligne 71 (remove random if you prefer a constant radius (e.g. 50))

//-----------------------------------------------------------------------------------//

const expansionRate = 0.5; //speed of the expansion of the targets
let move = 0.5; //movement speed of the targets 
let radius;
let x, y;
let score = 0;
let clickCount = 0;
let targets = [];
let Radius = [];
let timeLimit = 3; 
let countDown;
let starttime;
let Time = [];

function preload() {
  img = loadImage('/uploads/antkln/1669724251.png');
  a1 = loadImage('/uploads/antkln/chiffre1b.jpg');
  a2 = loadImage('/uploads/antkln/chiffre2b.jpg');
  a3 = loadImage('/uploads/antkln/chiffre3b.jpg');
  SOUND_SHOT = loadSound('/uploads/antkln/shotsound.mp3');
  MUSIC_BACK = loadSound('/uploads/antkln/videogame11.mp3'); //videogame22 // videogame
}

function setup() {    
    createCanvas(1000, 500); //(800, 400)
    sizeSlider = createSlider(10, 80, 50);// change size of targets but do not work on Ancient Brain
    //sizeSlider.style('width', '80px');
    MUSIC_BACK.play();
    MUSIC_BACK.loop();
}

function draw() {
    background(0);
    //noStroke();
    let currentTime = int(millis() / 1000); //convert time to second as an integer
    countDown = timeLimit - currentTime;
    image(a3, 0, 0, width, height);
    if (countDown < 2) {
        image(a2, 0, 0, width, height);
        currentTime = int(millis() / 1000);
        countDown = timeLimit - currentTime;
    }
    if (countDown < 1) {
        image(a1, 0, 0, width, height);
        currentTime = int(millis() / 1000);
        countDown = timeLimit - currentTime;
    }
    if (countDown < 0) {
        background(0);
        noFill();
        noStroke();
        //radius = sizeSlider.value(); not working (just initialize at 50)
        textSize(25);
        fill(240, 255, 250); // color for "Accuracy"
        let accuracy = score / clickCount;
        var roundedString = accuracy.toFixed(4);
        var rounded = Number(roundedString);
        text('Accuracy: ' + rounded*100 + '%', width-200, 25);
        
        if (targets.length < maxBalls) {
            xx = random(width);
            yy = random(height);
            radius = random(20, 80); //change radius here 
            append(Radius, radius);
            append(targets, new Target(xx, yy, radius)); 
            //appear = millis().toFixed(0)/1000;
            //disappear = 5-appear+4.1;
            //append(Time, disappear);
  //          text(disappear, width-200, 80);
        }
        
        for (let i = targets.length - 1; i >= 0; i--) {
            targets[i].expand(expansionRate);
            targets[i].show();
            //targets[i].movingx(move);
            //if (Time[i] < 0) {
                //targets.splice(i, 1);
                //Radius.splice(i, 1);      
            //}
            //if (targets[i].x < 400) {
            //    m = -m; //or m=0 //or targets pop and new one appear ? 
            //}
        }

        starttime = millis().toFixed(0)/1000;
        end = chosenTime-starttime+4.1; //I calculated 1.1 second to read the code and display the 3 images
        fill(240, 240, 240);
        text(end, width-50, 50);
        if (end <= 0) {
            clear();
            // const score2 = Object.assign({}, score); // the score should not change once the game is over
            fill(0, 0, 0);
            text("Congratulation!!!\nYou have a score of " + score + " targets in " + chosenTime + "s.\nYour accuracy is: " + rounded*100 + '%\nReload to try again!\nPRESS RIGHT_ARROW TO RELOAD\nPRESS LEFT_ARROW TO QUIT ' , width/3, height/3);
        } 
    }
}

function keyPressed() {
    if (keyCode === RIGHT_ARROW) {
        window.location.reload();
    } 
    else if (keyCode === LEFT_ARROW) {
        window.open('', '_self', '');
        window.close();
    }
}

function mousePressed() {
    SOUND_SHOT.play();
    SOUND_SHOT.setVolume(0.4);
    clickCount++;
    let a = 0;
    for (var i = targets.length - 1; i >= 0; i--) { 
        if (targets[i].test() < Radius[i]/2) { 
            targets.splice(i, 1);
            Radius.splice(i, 1);
            a++; 
        }
    }
    if (a>=1){ 
        score++;
    }
    a = 0;
}

class Target {
  constructor(x, y, s) {
    this.x = x;
    this.y = y;
    this.max = s;
    this.size = 0;
    this.color = color(random(50, 255), random(50, 255), random(50, 255)); //if black, we won't see it
  }
  show() {
    fill(this.color);
    //image(img, this.x, this.y, this.size, this.size); // if using image, add this.size/2 in the test function line 147 (explain in the report)
    ellipse(this.x, this.y, this.size); // if using ellipse, you have to remove this.size/2 in the test function line 147
  } 
  test() {
    return (dist(this.x, this.y, mouseX, mouseY)); // (for ellipse) return (dist(this.x + this.size/2, this.y + this.size/2, mouseX, mouseY)); // (for img)
  }
  expand(exprate) {
    this.size= constrain(this.size + exprate, 0, this.max); //this.size from this.size (=0 here) to this.max=radius with a expansion speed of exprate
  }
  movingx(m) {
      this.x = this.x + m; //move is the speed of the target
      //if (this.x > 300) {
      //    m = - m; //or m=0 //or targets pop and new one appear ? 
      //}
  }
}