Skip to content

Scale

Game made during a code-together discussion with students, using the prompt "Heavy" from Inktober 2025, day 9.

Draw two shapes, then guess which one is heavier (that is, has a larger area). Get more point for guessing between shapes that are very close in area.

A scale, with prompts to draw the left / right shape, and guess which is heavier.

function setup() {
  createCanvas(400, 330)
}

let mode = "shapeL";
let shapeL = [];
let shapeR = [];
let shapeLArea = 0;
let shapeRArea = 0;
let scaleAngle = 0;
let scaleAngleV = 0;
let points = 0;
let t = 0;
let guess = "";

function draw() {
  background(220);
  textSize(20);
  textAlign(CENTER, CENTER);
  if (mode == "guess") {
    scaleAngleV = (cos(t / 23) / 23) * 0.1;
    t += (deltaTime / 1000) * 60;
  }
  if (mode == "weight" || mode == "finish") {
    let areaDiff = shapeRArea - shapeLArea;
    scaleAngleV += pow(abs(areaDiff), 1/4) * Math.sign(areaDiff) * 0.00001;
  }
  scaleAngle += scaleAngleV;
  if (abs(scaleAngle) > 0.3) {
    scaleAngle = Math.sign(scaleAngle) * 0.3;
    scaleAngleV = -scaleAngleV * 0.1;
    if (
      mode == "weight" &&
      Math.sign(scaleAngle) == Math.sign(shapeRArea - shapeLArea) &&
      abs(scaleAngleV) < 0.001
    ) {
      mode = "finish";
    }
  }
  if (
      mode == "weight" && shapeRArea == shapeLArea &&
      abs(scaleAngleV) < 0.001
    ) {
      mode = "finish";
    }
  push();
  translate(200, 200);
  rotate(scaleAngle);
  drawScaleArm();
  push();
  scale(-1, 1);
  drawScaleArm();
  pop();
  push();
  translate(-95, 0);
  rotate(-scaleAngle);
  line(-80, 0, 80, 0);
  if (mode == "shapeL") {
    drawShapeArea("Draw left shape");
  }
  drawShape(shapeL, mode == "guess" || guess == "L");
  pop();
  push();
  translate(95, 0);
  rotate(-scaleAngle);
  line(-80, 0, 80, 0);
  if (mode == "shapeR") {
    drawShapeArea("Draw right shape");
  }
  drawShape(shapeR, mode == "guess" || guess == "R");
  pop();
  pop();
  if (mode == "guess") {
    text("Guess which one is heavier", 200, 280);
  }
  if (mode == "finish") {
    text(
      shapeLArea == shapeRArea
        ? "They are equal! 😮" :
      (guess == "L") == (shapeLArea > shapeRArea)
        ? "Correct! 🎉\n+" + calcPoints()
        : "Incorrect! 🫤\n-" + calcPoints(),
      200,
      280
    );
  }
  if (points != 0) {
    textAlign(RIGHT, TOP);
    text(points, 390, 10);
  }
}

function mousePressed() {
  if (mode == "shapeL") {
    if (mouseX < 190 && mouseX > 20 && mouseY < 200 && mouseY > 60) {
      shapeL.push([mouseX - 200 + 95 + random(-1,1), mouseY - 200 + random(-1,1)]);
    } else if (shapeL.length >= 3) {
      mode = "shapeR";
    }
  }
  if (mode == "shapeR") {
    if (mouseX < 480 && mouseX > 210 && mouseY < 200 && mouseY > 60) {
      shapeR.push([mouseX - 200 - 95 + random(-1,1), mouseY - 200 + random(-1,1)]);
    } else if (shapeR.length >= 3) {
      mode = "guess";
      shapeLArea = calcShapeArea(shapeL);
      shapeRArea = calcShapeArea(shapeR);
      return;
    }
  }
  if (mode == "guess") {
    scaleAngleV += random(-0.2, 0.2);
    if (mouseX < 190) {
      guess = "L";
      mode = "weight";
    } else if (mouseX > 210) {
      guess = "R";
      mode = "weight";
    }
  }
  if (mode == "finish") {
    points +=
      (shapeLArea == shapeRArea ? 0 : (guess == "L") == shapeLArea > shapeRArea ? 1 : -1) * calcPoints();
    shapeL = [];
    shapeR = [];
    mode = "shapeL";
    scaleAngle = 0;
    scaleAngleV = 0;
    guess = "";
    t = 0
  }
}

function drawScaleArm() {
  line(0, 0, 10, 25);
  line(95, 0, 85, 25);
  line(10, 25, 85, 25);
}
function drawShapeArea(txt) {
  text(txt, 0, -150);
  push();
  stroke("#3E4943");
  fill(
    lerpColor(
      color("#A6E7C4"),
      color("#C8ECD7"),
      sin(millis() / 300) / 2 + 0.5
    )
  );
  rect(-75, -135, 150, 130);
  pop();
}
function drawShape(shapeP, selected) {
  if (selected) {
    fill(
      lerpColor(
        color("#F2EAA8"),
        color("#F4E4C3"),
        sin(millis() / 300) / 2 + 0.5
      )
    );
  }
  beginShape();
  for (let p of shapeP) {
    vertex(...p);
  }
  endShape(CLOSE);
}
function calcShapeArea(shapeP) {
  let area = 0;
  for (let i = 0; i < shapeP.length; i++) {
    let p_i = shapeP[i];
    let p_i1 = shapeP[(i + 1) % shapeP.length];
    area += (p_i[0] + p_i1[0]) * (p_i[1] - p_i1[1]);
  }
  return abs(area / 2);
}
function calcPoints() {
  return round(1000 / (abs(shapeLArea - shapeRArea) + 10));
}

(Originally seen at https://editor.p5js.org/bojidar-bg/sketches/eEfTsJloa)

Experiments tagged p5 (63/85)

Experiments tagged game (7/11)

Experiments on this site (63/85)