Code Sketch


harshada kumbhar
By: Mhalsakant School
Category: Art
cleari()
originBottomLeft()

class Sketch {

  var t = 0.0
  var bob = 0.0
  var spin = 0.0
  var pulse = 0.0
  var blink = 0.0
  var wave = 0.0

  var robotX = 0.0
  var robotY = 190.0

  var targetX = 0.0
  var targetY = 190.0

  var lookX = 0.0
  var lookY = 0.0

  var waving = false
  var clicked = false

  def clamp(v: Double, lo: Double, hi: Double): Double =
    math.max(lo, math.min(hi, v))

  def alpha(v: Double): Int =
    clamp(v, 0.0, 255.0).toInt

  def setup(c: CanvasDraw): Unit = {
    c.background(5, 12, 30)
  }

  // ------------------------------------------------
  // SPACE BACKGROUND
  // ------------------------------------------------

  def drawBackground(c: CanvasDraw): Unit = {

    c.background(5, 12, 30)

    for (i <- 0 until 70) {

      val x = ((i * 97) % cwidth).toDouble
      val y = ((i * 61) % cheight).toDouble

      val brightness =
        alpha(90 + 100 * math.abs(math.sin(t + i)))

      c.noStroke()
      c.fill(90, 210, 255, brightness)

      c.ellipse(
        x,
        y + math.sin(t + i) * 3,
        2 + math.sin(t + i) * 0.7,
        2 + math.sin(t + i) * 0.7
      )
    }

    // Digital floor
    c.stroke(0, 130, 210, 55)
    c.strokeWeight(1)

    for (i <- 0 until 15) {
      val y = 20.0 + i * 12

      c.line(0, y, cwidth, y)
    }

    for (i <- 0 until 22) {
      val x = i * cwidth / 21.0

      c.line(
        cwidth / 2.0,
        20,
        x,
        180
      )
    }
  }

  // ------------------------------------------------
  // HOLOGRAM PLATFORM
  // ------------------------------------------------

  def drawPlatform(c: CanvasDraw): Unit = {

    for (i <- 0 until 4) {

      val r = 90.0 + i * 17.0
      val a = alpha(170 - i * 30)

      c.noFill()
      c.stroke(0, 220, 255, a)
      c.strokeWeight(2)

      c.ellipse(
        cwidth / 2.0,
        75,
        r * 2,
        15 + i * 4
      )
    }

    c.fill(0, 180, 255, 35)
    c.noStroke()

    c.ellipse(
      cwidth / 2.0,
      76,
      180,
      22
    )
  }

  // ------------------------------------------------
  // ENERGY RINGS
  // ------------------------------------------------

  def drawEnergyRings(c: CanvasDraw): Unit = {

    val cx = cwidth / 2.0
    val cy = robotY - 5 + bob

    for (i <- 0 until 3) {

      val angle = spin + i * 2.1
      val rx = 80.0 + i * 12.0
      val ry = 12.0 + i * 4.0

      c.noFill()
      c.stroke(
        0,
        210 + i * 10,
        255,
        alpha(170 - i * 35)
      )

      c.strokeWeight(2)

      c.ellipse(
        cx + math.cos(angle) * 10,
        cy + math.sin(angle) * 12,
        rx * 2,
        ry * 2
      )
    }
  }

  // ------------------------------------------------
  // ROBOT BODY
  // ------------------------------------------------

  def drawBody(c: CanvasDraw): Unit = {

    val x = cwidth / 2.0
    val y = robotY + bob

    // Shoulder energy glow
    c.noStroke()
    c.fill(0, 200, 255, 40)

    c.ellipse(x, y + 15, 125, 120)

    // Torso
    c.fill(45, 65, 90)
    c.stroke(70, 225, 255)
    c.strokeWeight(3)

    c.ellipse(
      x,
      y + 12,
      83,
      100
    )

    // Chest armor
    c.fill(20, 115, 155)
    c.stroke(100, 240, 255)

    c.ellipse(
      x,
      y + 22,
      55,
      58
    )

    // Energy core
    val core = alpha(150 + math.sin(pulse) * 100)

    c.noStroke()
    c.fill(0, 220, 255, core)

    c.ellipse(
      x,
      y + 23,
      32,
      32
    )

    c.fill(230, 255, 255, 240)

    c.ellipse(
      x,
      y + 23,
      13,
      13
    )

    // Core rays
    c.stroke(100, 245, 255, 200)
    c.strokeWeight(2)

    for (i <- 0 until 8) {

      val a = i * math.Pi / 4.0
      val x1 = x + math.cos(a) * 20
      val y1 = y + 23 + math.sin(a) * 20
      val x2 = x + math.cos(a) * 28
      val y2 = y + 23 + math.sin(a) * 28

      c.line(x1, y1, x2, y2)
    }

    // Waist
    c.fill(40, 70, 100)
    c.stroke(70, 210, 255)

    c.rect(
      x - 25,
      y - 30,
      50,
      20
    )

    // Legs
    c.stroke(100, 190, 220)
    c.strokeWeight(12)

    c.line(x - 20, y - 32, x - 25, y - 62)
    c.line(x + 20, y - 32, x + 25, y - 62)

    // Boots
    c.strokeWeight(2)
    c.fill(30, 65, 90)

    c.rect(x - 39, y - 70, 29, 12)
    c.rect(x + 10, y - 70, 29, 12)

    c.fill(0, 230, 255, 180)
    c.noStroke()

    c.rect(x - 35, y - 64, 21, 3)
    c.rect(x + 14, y - 64, 21, 3)
  }

  // ------------------------------------------------
  // ROBOT ARMS
  // ------------------------------------------------

  def drawArms(c: CanvasDraw): Unit = {

    val x = cwidth / 2.0
    val y = robotY + bob

    val swing =
      if (waving) math.sin(wave) * 20
      else math.sin(t * 2) * 5

    // Left arm
    c.stroke(90, 180, 220)
    c.strokeWeight(12)

    c.line(
      x - 39, y + 38,
      x - 60, y + 10
    )

    c.stroke(0, 230, 255)
    c.strokeWeight(3)

    c.fill(30, 90, 125)

    c.ellipse(
      x - 60,
      y + 10,
      20,
      20
    )

    c.stroke(90, 180, 220)
    c.strokeWeight(9)

    c.line(
      x - 60, y + 10,
      x - 70, y - 12
    )

    c.fill(70, 190, 230)
    c.noStroke()

    c.ellipse(
      x - 70,
      y - 15,
      17,
      17
    )

    // Right arm
    c.stroke(90, 180, 220)
    c.strokeWeight(12)

    c.line(
      x + 39, y + 38,
      x + 60, y + 10
    )

    c.fill(30, 90, 125)
    c.stroke(0, 230, 255)
    c.strokeWeight(3)

    c.ellipse(
      x + 60,
      y + 10,
      20,
      20
    )

    c.stroke(90, 180, 220)
    c.strokeWeight(9)

    c.line(
      x + 60, y + 10,
      x + 72, y + swing
    )

    // Hand
    c.fill(80, 210, 245)
    c.noStroke()

    c.ellipse(
      x + 72,
      y + swing,
      18,
      18
    )

    // Digital fingers
    c.stroke(100, 240, 255)
    c.strokeWeight(2)

    for (i <- 0 until 3) {

      c.line(
        x + 76,
        y + swing + i * 4 - 4,
        x + 85,
        y + swing + i * 4 - 7
      )
    }
  }

  // ------------------------------------------------
  // ROBOT HEAD
  // ------------------------------------------------

  def drawHead(c: CanvasDraw): Unit = {

    val x = cwidth / 2.0 + lookX * 0.4
    val y = robotY + bob + 83

    // Head glow
    c.noStroke()
    c.fill(0, 190, 255, 40)

    c.ellipse(x, y, 105, 95)

    // Head
    c.fill(45, 65, 85)
    c.stroke(100, 235, 255)
    c.strokeWeight(3)

    c.rect(
      x - 38,
      y - 30,
      76,
      60
    )

    // Face display
    c.fill(5, 20, 40)
    c.noStroke()

    c.rect(
      x - 29,
      y - 20,
      58,
      39
    )

    // Blinking eyes
    val eyeHeight =
      if (math.sin(blink) > 0.97) 2.0 else 10.0

    c.fill(0, 235, 255, 240)

    c.ellipse(
      x - 15 + lookX,
      y + 2 + lookY,
      11,
      eyeHeight
    )

    c.ellipse(
      x + 15 + lookX,
      y + 2 + lookY,
      11,
      eyeHeight
    )

    // Mouth animation
    c.stroke(0, 230, 255)
    c.strokeWeight(3)

    val mouth = 3 + math.abs(math.sin(t * 6)) * 7

    c.line(
      x - 10,
      y - 11,
      x + 10,
      y - 11
    )

    c.noFill()

    c.ellipse(
      x,
      y - 10,
      15,
      mouth
    )

    // Side ears
    c.fill(40, 100, 140)
    c.stroke(0, 220, 255)
    c.strokeWeight(2)

    c.ellipse(x - 43, y, 12, 24)
    c.ellipse(x + 43, y, 12, 24)

    // Antenna
    c.stroke(100, 210, 245)
    c.strokeWeight(3)

    c.line(
      x,
      y + 30,
      x,
      y + 43
    )

    c.fill(
      0,
      220,
      255,
      alpha(130 + math.sin(t * 5) * 100)
    )

    c.noStroke()

    c.ellipse(
      x,
      y + 47,
      12,
      12
    )
  }

  // ------------------------------------------------
  // HOLOGRAM HUD
  // ------------------------------------------------

  def drawHUD(c: CanvasDraw): Unit = {

    val x = cwidth / 2.0

    c.fill(100, 240, 255)
    c.noStroke()

    c.text(
      "N E U R O  -  A I",
      x - 60,
      cheight - 35
    )

    c.fill(50, 190, 230, 220)

    c.text(
      "HOLOGRAM SYSTEM ONLINE",
      x - 90,
      cheight - 55
    )

    c.text(
      "ENERGY: " +
        (80 + (math.sin(t) * 15).toInt) +
        "%",
      25,
      cheight - 35
    )

    c.text(
      "CORE: ACTIVE",
      25,
      cheight - 55
    )

    c.text(
      "CLICK TO ACTIVATE",
      cwidth - 145,
      cheight - 35
    )

    c.text(
      "AI ROBOT v2.0",
      cwidth - 145,
      cheight - 55
    )

    // Corner brackets
    c.stroke(0, 190, 255, 180)
    c.strokeWeight(2)
    c.noFill()

    c.line(15, cheight - 75, 15, cheight - 110)
    c.line(15, cheight - 75, 50, cheight - 75)

    c.line(cwidth - 15, cheight - 75, cwidth - 15, cheight - 110)
    c.line(cwidth - 15, cheight - 75, cwidth - 50, cheight - 75)
  }

  // ------------------------------------------------
  // CLICK RING
  // ------------------------------------------------

  def drawClickEffect(c: CanvasDraw): Unit = {

    if (clicked) {

      val r = 20 + math.abs(math.sin(t * 3)) * 30

      c.noFill()
      c.stroke(0, 240, 255, 180)
      c.strokeWeight(2)

      c.ellipse(
        targetX,
        targetY,
        r * 2,
        r * 2
      )

      c.stroke(0, 170, 255, 100)

      c.ellipse(
        targetX,
        targetY,
        r * 2.6,
        r * 2.6
      )
    }
  }

  // ------------------------------------------------
  // MAIN ANIMATION LOOP
  // ------------------------------------------------

  def drawLoop(c: CanvasDraw): Unit = {

    t += 0.04
    spin += 0.035
    pulse += 0.09
    blink += 0.035

    drawBackground(c)

    if (isMousePressed) {

      targetX = mouseX.toDouble
      targetY = mouseY.toDouble

      clicked = true
      waving = true
    }


    drawPlatform(c)
    drawEnergyRings(c)
    drawBody(c)
    drawArms(c)
    drawHead(c)
    drawClickEffect(c)
    drawHUD(c)
  }
}

val sketch = new Sketch
    lookX = clamp(
      (targetX - cwidth / 2.0) * 0.025,
      -5,
      5
    )

    lookY = clamp(
      (targetY - robotY) * 0.02,
      -4,
      4
    )

    bob = math.sin(t * 2.0) * 3.0

    if (waving) {
      wave += 0.25

      if (wave > 12) {
        wave = 0
        waving = false
      }
    }
canvasSketch(sketch)