Code Sketch


Amar gurav
By: Mhalsakant School
Category: Programming
cleari()
originBottomLeft()

class Sketch {

  // ==================== VARIABLES ====================

  var t = 0.0
  var bob = 0.0
  var headTurn = 0.0
  var armPhase = 0.0
  var blink = 0.0
  var scan = 0.0

  var robotX = cwidth / 2.0
  var robotY = 185.0

  var targetX = cwidth / 2.0
  var targetY = 185.0

  var lookX = 0.0
  var lookY = 0.0

  var waving = false
  var clicked = false

  // ==================== PARTICLES ====================

  case class Particle(
    var x: Double,
    var y: Double,
    vx: Double,
    vy: Double,
    phase: Double
  )

  val particles = Array.tabulate(55) { i =>
    Particle(
      (i * 137.5) % cwidth,
      (i * 83.7) % cheight,
      math.sin(i * 2.1) * 0.35,
      math.cos(i * 1.7) * 0.3,
      i * 0.41
    )
  }

  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

  // ==================== REQUIRED SETUP ====================

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

  // ==================== BACKGROUND ====================

  def drawBackground(c: CanvasDraw): Unit = {
    c.background(5, 12, 28)

    c.noStroke()
    c.fill(8, 28, 48)
    c.rect(0, 0, cwidth, 55)

    c.fill(0, 100, 180, 25)
    c.ellipse(
      cwidth / 2.0,
      cheight / 2.0,
      480,
      360
    )
  }

  // ==================== PARTICLE ENGINE ====================

  def drawParticles(c: CanvasDraw): Unit = {
    for (p <- particles) {
      p.x += p.vx
      p.y += p.vy

      if (p.x < 0) p.x = cwidth.toDouble
      if (p.x > cwidth) p.x = 0.0
      if (p.y < 0) p.y = cheight.toDouble
      if (p.y > cheight) p.y = 0.0

      val pulse =
        (math.sin(t * 3.0 + p.phase) + 1.0) / 2.0

      c.noStroke()
      c.fill(
        0,
        170 + (pulse * 80).toInt,
        255,
        alpha(70 + pulse * 150)
      )

      c.ellipse(
        p.x,
        p.y,
        2 + pulse * 2,
        2 + pulse * 2
      )
    }
  }

  // ==================== TV ====================

  def drawTV(c: CanvasDraw): Unit = {
    val x = cwidth / 2.0
    val y = 200.0

    // Shadow
    c.noStroke()
    c.fill(0, 0, 0, 100)
    c.ellipse(x, 65, 470, 35)

    // TV shell
    c.fill(22, 32, 45)
    c.stroke(0, 160, 210)
    c.strokeWeight(3)
    c.rect(x - 260, y - 105, 520, 285)

    // Screen
    c.fill(3, 13, 27)
    c.stroke(0, 205, 245, 220)
    c.strokeWeight(3)
    c.rect(x - 225, y - 70, 450, 220)

    // Screen glow
    c.noStroke()
    c.fill(0, 130, 210, 35)
    c.ellipse(x, y + 25, 390, 170)

    // Moving scanline
    val sy = y - 60 + (scan % 200.0)

    c.stroke(0, 220, 255, 120)
    c.strokeWeight(2)
    c.line(x - 215, sy, x + 215, sy)

    // TV buttons
    c.noStroke()
    c.fill(0, 210, 255, alpha(120 + math.sin(t * 4) * 100))
    c.ellipse(x + 205, y - 87, 8, 8)

    c.fill(75, 90, 105)
    c.ellipse(x - 35, y - 87, 9, 9)
    c.ellipse(x, y - 87, 9, 9)
    c.ellipse(x + 35, y - 87, 9, 9)

    // Stand
    c.fill(25, 38, 52)
    c.stroke(5, 15, 25)
    c.strokeWeight(2)
    c.rect(x - 48, 45, 96, 28)
    c.rect(x - 95, 32, 190, 13)
  }

  // ==================== ENERGY RINGS ====================

  def drawRings(c: CanvasDraw): Unit = {
    c.noFill()

    for (i <- 0 until 4) {
      val phase = (t * 28 + i * 25) % 100
      val r = 35 + phase
      val a = alpha(120 * (1 - phase / 100))

      c.stroke(0, 205, 255, a)
      c.strokeWeight(1.5)
      c.ellipse(
        robotX,
        robotY + bob,
        r * 1.7,
        r * 0.4
      )
    }
  }

  // ==================== ROBOT LOWER BODY ====================

  def drawBase(c: CanvasDraw): Unit = {
    val x = robotX
    val y = robotY + bob

    c.fill(130, 150, 170)
    c.stroke(45, 60, 75)
    c.strokeWeight(2)

    c.ellipse(x - 22, y - 28, 28, 18)
    c.ellipse(x + 22, y - 28, 28, 18)

    c.fill(155, 175, 190)
    c.rect(x - 24, y - 53, 48, 24)

    c.noStroke()
    c.fill(0, 200, 255, 180)
    c.ellipse(x, y - 60, 42, 9)
  }

  // ==================== ROBOT BODY ====================

  def drawBody(c: CanvasDraw): Unit = {
    val x = robotX
    val y = robotY + bob

    c.fill(215, 225, 235)
    c.stroke(45, 60, 75)
    c.strokeWeight(2)
    c.ellipse(x, y + 20, 90, 100)

    // Shoulders
    c.fill(25, 100, 140)
    c.stroke(0, 215, 255)
    c.ellipse(x - 44, y + 43, 25, 28)
    c.ellipse(x + 44, y + 43, 25, 28)

    // Reactor
    val power = alpha(140 + math.sin(t * 3) * 100)

    c.noStroke()
    c.fill(0, 170, 240, power)
    c.ellipse(x, y + 28, 28, 28)

    c.fill(220, 250, 255)
    c.ellipse(x, y + 28, 10, 10)

    c.fill(10, 65, 95)
    c.text("AI", x - 7, y + 31)
  }

  // ==================== ROBOT ARMS ====================

  def drawArms(c: CanvasDraw): Unit = {
    val x = robotX
    val y = robotY + bob

    val swing =
      if (waving) math.sin(armPhase) * 20
      else math.sin(t * 2) * 3

    // Left arm
    c.stroke(215, 225, 235)
    c.strokeWeight(10)
    c.line(x - 44, y + 43, x - 63, y + 12)
    c.line(x - 63, y + 12, x - 72, y - 18)

    c.fill(215, 225, 235)
    c.stroke(50, 70, 85)
    c.strokeWeight(2)
    c.ellipse(x - 72, y - 26, 17, 18)

    // Right arm
    val handY = y + 5 + swing

    c.stroke(215, 225, 235)
    c.strokeWeight(10)
    c.line(x + 44, y + 43, x + 63, y + 15)
    c.line(x + 63, y + 15, x + 73, handY)

    c.fill(215, 225, 235)
    c.stroke(50, 70, 85)
    c.strokeWeight(2)
    c.ellipse(x + 73, handY, 17, 19)

    // Fingers
    c.stroke(0, 200, 240)
    c.strokeWeight(1.5)

    for (i <- 0 until 3) {
      c.line(
        x + 74,
        handY - 5 + i * 4,
        x + 83,
        handY - 7 + i * 4
      )
    }
  }

  // ==================== ROBOT HEAD ====================

  def drawHead(c: CanvasDraw): Unit = {
    val x = robotX + headTurn
    val y = robotY + bob + 73

    // Head
    c.fill(225, 232, 240)
    c.stroke(45, 60, 80)
    c.strokeWeight(2.5)
    c.rect(x - 34, y - 28, 68, 56)

    // Forehead
    c.fill(20, 100, 135)
    c.stroke(0, 220, 255)
    c.strokeWeight(2)
    c.ellipse(x, y + 20, 32, 9)

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

    c.noStroke()
    c.fill(5, 15, 25)
    c.ellipse(x - 14, y + 3, 11, eyeHeight)
    c.ellipse(x + 14, y + 3, 11, eyeHeight)

    // Pupils
    c.fill(0, 230, 255)
    c.ellipse(x - 14 + lookX, y + 3 + lookY, 5, 5)
    c.ellipse(x + 14 + lookX, y + 3 + lookY, 5, 5)

    // Animated mouth
    c.stroke(35, 60, 75)
    c.strokeWeight(2)

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

    c.noFill()
    c.ellipse(x, y - 14, 16, mouthHeight)

    // Ears
    c.fill(175, 195, 210)
    c.stroke(55, 70, 85)
    c.strokeWeight(2)
    c.ellipse(x - 38, y, 12, 22)
    c.ellipse(x + 38, y, 12, 22)

    c.noStroke()
    c.fill(0, 220, 255)
    c.ellipse(x - 38, y, 5, 8)
    c.ellipse(x + 38, y, 5, 8)

    // Antenna
    c.stroke(100, 120, 140)
    c.strokeWeight(2)
    c.line(x, y + 28, x, y + 44)

    c.noStroke()
    c.fill(0, 220, 255, alpha(130 + math.sin(t * 5) * 100))
    c.ellipse(x, y + 48, 10, 10)
  }

  // ==================== SPEECH BUBBLE ====================

  def drawSpeech(c: CanvasDraw): Unit = {
    val x = robotX + 95
    val y = robotY + 105

    c.fill(235, 250, 255, 245)
    c.stroke(0, 190, 225)
    c.strokeWeight(2)
    c.rect(x, y, 175, 82)

    c.noStroke()
    c.fill(10, 75, 105)

    c.text("AI SYSTEM ONLINE", x + 10, y + 62)
    c.text("HELLO HUMAN!", x + 10, y + 43)
    c.text("I AM YOUR ROBOT", x + 10, y + 25)

    val dot = (math.sin(t * 5) + 1) / 2

    c.fill(0, 170, 230, alpha(100 + dot * 150))
    c.ellipse(x + 140, y + 12, 5, 5)
    c.ellipse(x + 151, y + 12, 5, 5)
    c.ellipse(x + 162, y + 12, 5, 5)
  }

  // ==================== HUD ====================

  def drawHUD(c: CanvasDraw): Unit = {
    val pulse = (math.sin(t * 4) + 1) / 2

    c.noStroke()
    c.fill(0, 10, 25, 220)
    c.rect(15, cheight - 95, 190, 70)

    c.stroke(0, 190, 255)
    c.strokeWeight(1)
    c.noFill()
    c.rect(15, cheight - 95, 190, 70)

    c.fill(100, 235, 255)
    c.noStroke()
    c.text("NEURAL CORE v4", 25, cheight - 78)
    c.text("STATUS: ONLINE", 25, cheight - 60)

    c.fill(0, 180, 255, alpha(130 + pulse * 125))
    c.ellipse(185, cheight - 75, 7, 7)

    c.fill(35, 60, 80)
    c.rect(25, cheight - 49, 155, 5)

    c.fill(0, 190, 255)
    c.rect(25, cheight - 49, 155 * (0.65 + pulse * 0.3), 5)
  }

  // ==================== CLICK EFFECT ====================

  def drawClickEffect(c: CanvasDraw): Unit = {
    if (clicked) {
      val r = 15 + math.sin(t * 5) * 5

      c.noFill()
      c.stroke(0, 220, 255, 150)
      c.strokeWeight(2)
      c.ellipse(targetX, targetY, r, r)
    }
  }

  // ==================== REQUIRED DRAW LOOP ====================

  def drawLoop(c: CanvasDraw): Unit = {
    t += 0.04
    bob = math.sin(t * 2) * 2
    scan += 1.5
    blink += 0.035

    drawBackground(c)
    drawParticles(c)
    drawTV(c)

    // Interaction
    if (isMousePressed) {
      targetX = clamp(
        mouseX.toDouble,
        cwidth / 2.0 - 190,
        cwidth / 2.0 + 190
      )

      targetY = clamp(
        mouseY.toDouble,
        115,
        315
      )

      clicked = true
      waving = true
    }

    // Eye tracking
    lookX = clamp((targetX - robotX) * 0.03, -4, 4)
    lookY = clamp((targetY - robotY) * 0.03, -3, 3)

    // Head follows target
    headTurn += (
      (targetX - robotX) * 0.015 - headTurn
    ) * 0.08

    headTurn = clamp(headTurn, -8, 8)

    // Wave animation
    if (waving) {
      armPhase += 0.24

      if (armPhase > 12) {
        waving = false
        armPhase = 0
      }
    }

    // Draw order
    drawRings(c)
    drawBase(c)
    drawBody(c)
    drawArms(c)
    drawHead(c)
    drawSpeech(c)
    drawHUD(c)
    drawClickEffect(c)

    c.fill(100, 220, 255)
    c.noStroke()
    c.text(
      "AI ROBOT SYSTEM // TOUCH TO INTERACT",
      cwidth / 2.0 - 130,
      15
    )
  }
}

// ==================== START ====================

val sketch = new Sketch
canvasSketch(sketch)