Code viewer for World: Random shape game
let shapes; //all available shapes
let haveShape = false;
let newShape; //the default or currently selected shape
const canvasShapes = []; //all canvas shapes drawn to the screen

function setup() {
  createCanvas(800, 600, WEBGL); //canvas size
  //an array of objects that contains a shape and the number of dimensions of that shape
  shapes = [{type: plane, dims: 1}, //type of shape and the number of dimensions of that shape
            {type: box, dims: 3},
            {type: cylinder, dims: 2},
            {type: cone, dims: 2},
            {type: torus, dims: 2},
            {type: sphere, dims: 1}];
            
    AB.msg("Use mouse wheel to select a shape. Left click to place it.");	
}
//returns an array of size n with values put through the map function func(passed as a callback)
function getRandom(n, func) {
  return Array.from({length: n}, func);
}
//create a random shape
//col = random color; shp = shape; dims = random dimensions; axis = rotation axis
function randomShape() {
  const col = getRandom(3, _ => random(255)); //random color requires three values rgb
  const shp = random(shapes); //random shape
  const dims = getRandom(shp.dims, _ => random(20,50)); //use random shapes's number of dimensions to create an array of random dimensions 
  const axis = getRandom(3, _ => Math.floor(random(2)));//rotation on three axes(0 or 1); if 0 no rotation on that axis
  //return new shape object
  return {shape: shp, 
          dimensions: dims, 
          color: col, 
          pos: null,
          axis,
          speed: random(0.01, 0.1) // random rotation speed
         };
}
//when mouse wheel is used create a new shape
//by resetting the haveShape variable we run the randomShape method in the draw function
function mouseWheel() {
  haveShape = false;
  newShape = null;
}
//when mouse clicked save current position in the shape's object and push it
//to the canvasShapes array to be rendered
function mouseClicked() {
  const posX = mouseX - width/2; //determine position of mouse pointer on the x axis
  const posY = mouseY - height/2;// y axis
  newShape.pos = {x: posX, y: posY}; // save positions to the currently selected shape
  canvasShapes.push(newShape); //push to all shapes array to be drawn to the screen
  //reset the default shape
  haveShape = false; 
  newShape = null;
}

function drawShapes() {
  //for loop to draw shapes
  canvasShapes.forEach(cShape => {
    drawShape(cShape);
  });
}
//draw shape to the screen
function drawShape(s) {
    //destructure the shape object s to get individual properties
  const {color, shape, dimensions, pos, axis: [x,y,z], speed} = s;
      
      push();
      if(pos) {
          //if pos is present that means that this shape is from the canvasShapes array
        translate(pos.x, pos.y);
      } else { //currently selected(with mouse wheel) or default shape(follows mouse pointer)
        translate(mouseX - width/2, mouseY - height/2);
      }
      //unfold the color array e.g. 
      //color = [125,26,250] = fill(...[125, 26, 250]) = fill(125, 26, 250)
      fill(...color);
      //set rotation and speed(no rotation on that axis if x, y or z is 0)
      rotateX(frameCount * speed * x);
      rotateY(frameCount * speed * y);
      rotateZ(frameCount * speed * z);
      //call whatever shape it is and unfold the dimensions array
      shape.type(...dimensions);
      pop();
}

function draw() {
    //draw background
    background(175);

    if(!haveShape) { //if haveShape = false create a new random shape
      haveShape = true;
      newShape = randomShape();
      //noStroke();
    } else {
      //draw a default shape or currently selected(with mouse wheel) shape(follows the mouse pointer)
      drawShape(newShape);
    }
    //draw all shapes
    drawShapes();
}