Code Sketch


shravani tingare
By: Mhalsakant School
Category: Art
// ============================================================
// ? AI SMART TV ROBOT ? ADVANCED BLUE EDITION
// KOJO / SCALA
// ============================================================

cleari()
originBottomLeft()

// ------------------------------------------------------------
// GLOBAL ANIMATION VALUES
// ------------------------------------------------------------

var t = 0.0
var scan = 0.0
var pulse = 0.0
var blink = 0.0
var wave = 0.0
var bob = 0.0
var headTurn = 0.0

var talking = true
var waving = false
var clicked = false

var targetX = 0.0
var targetY = 0.0

// ------------------------------------------------------------
// HELPERS
// ------------------------------------------------------------

def clamp(v: Double, a: Double, b: Double): Double =
  math.max(a, math.min(b, v))

def a(v: Double): Int =
  clamp(v, 0, 255).toInt

// ------------------------------------------------------------
// SETUP
// ------------------------------------------------------------

val sketch = new {

  def setup(c: CanvasDraw): Unit = {
    c.background(5, 10, 20)
  }

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

  def background(c: CanvasDraw): Unit = {

    c.background(5, 10, 20)

    // blue atmosphere
    c.noStroke()
    c.fill(0, 35, 65, 120)
    c.ellipse(
      cwidth / 2.0,
      cheight / 2.0,
      900,
      500
    )

    // floating particles
    for (i <- 0 until 45) {

      val px =
        15.0 + ((i * 97) % (cwidth - 30))

      val py =
        55.0 + ((i * 61) % (cheight - 90))

      val s =
        1.0 + math.sin(t * 2 + i) * 0.7

      c.fill(
        0,
        180,
        255,
        a(80 + math.sin(t + i) * 50)
      )

      c.ellipse(px, py, s * 2, s * 2)
    }

    // grid
    c.stroke(0, 100, 180, 35)
    c.strokeWeight(1)

    for (x <- 0 to cwidth.toInt by 40) {
      c.line(x, 0, x, cheight)
    }

    for (y <- 0 to cheight.toInt by 40) {
      c.line(0, y, cwidth, y)
    }
  }

  // ==========================================================
  // TV BODY
  // ==========================================================

  def tv(c: CanvasDraw): Unit = {

    val cx = cwidth / 2.0
    val ty = 210.0

    // shadow
    c.noStroke()
    c.fill(0, 0, 0, 150)
    c.ellipse(cx, 35, 650, 35)

    // outer body
    c.fill(12, 20, 32)
    c.stroke(0, 110, 190, 220)
    c.strokeWeight(5)

    c.rect(
      cx - 350,
      65,
      700,
      330
    )

    // blue outer glow
    c.noFill()
    c.stroke(
      0,
      180,
      255,
      a(120 + math.sin(pulse) * 70)
    )
    c.strokeWeight(3)

    c.rect(
      cx - 340,
      75,
      680,
      310
    )

    // screen
    c.fill(3, 15, 28)
    c.stroke(0, 210, 255, 220)
    c.strokeWeight(4)

    c.rect(
      cx - 300,
      105,
      430,
      245
    )

    // screen glow
    c.fill(0, 80, 150, 45)
    c.noStroke()
    c.ellipse(
      cx - 85,
      225,
      370,
      210
    )

    // scan lines
    for (i <- 0 until 18) {

      val yy =
        112 + i * 13

      c.stroke(0, 180, 255, 25)
      c.line(
        cx - 292,
        yy,
        cx + 122,
        yy
      )
    }

    // moving scan
    val sy =
      110 + (scan % 235)

    c.stroke(
      0,
      230,
      255,
      110
    )

    c.line(
      cx - 292,
      sy,
      cx + 122,
      sy
    )

    // TV buttons
    c.fill(25, 40, 55)
    c.stroke(0, 150, 220)
    c.strokeWeight(1)

    c.ellipse(cx + 175, 105, 12, 12)
    c.ellipse(cx + 200, 105, 12, 12)
    c.ellipse(cx + 225, 105, 12, 12)

    // power LED
    c.fill(
      0,
      220,
      255,
      a(120 + math.sin(t * 5) * 100)
    )
    c.noStroke()
    c.ellipse(cx + 315, 105, 9, 9)

    // stand
    c.fill(10, 18, 28)
    c.stroke(0, 100, 160)
    c.strokeWeight(3)

    c.rect(cx - 65, 40, 130, 28)
    c.rect(cx - 120, 28, 240, 12)
  }

  // ==========================================================
  // ROBOT
  // ==========================================================

  def robot(c: CanvasDraw): Unit = {

    val cx =
      cwidth / 2.0 - 85 + headTurn

    val cy =
      205 + bob

    // --------------------------------------------------------
    // ROBOT BASE
    // --------------------------------------------------------

    c.fill(45, 65, 80)
    c.stroke(0, 190, 255)
    c.strokeWeight(2)

    c.ellipse(
      cx,
      cy - 82,
      65,
      18
    )

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

    c.ellipse(
      cx,
      cy - 87,
      48,
      9
    )

    // --------------------------------------------------------
    // BODY
    // --------------------------------------------------------

    c.fill(190, 205, 215)
    c.stroke(30, 60, 80)
    c.strokeWeight(2)

    c.ellipse(
      cx,
      cy - 5,
      95,
      105
    )

    // chest blue panel
    c.fill(8, 50, 75)
    c.stroke(0, 210, 255)
    c.strokeWeight(2)

    c.rect(
      cx - 30,
      cy - 40,
      60,
      48
    )

    // reactor
    c.fill(
      0,
      220,
      255,
      a(150 + math.sin(pulse * 2) * 100)
    )

    c.ellipse(
      cx,
      cy - 17,
      25,
      25
    )

    c.fill(220, 255, 255)
    c.ellipse(cx, cy - 17, 8, 8)

    // AI text on chest
    c.fill(255, 255, 255)
    c.text("AI", cx - 9, cy - 18)

    // --------------------------------------------------------
    // ARMS
    // --------------------------------------------------------

    val handOffset =
      if (waving)
        math.sin(wave) * 18
      else
        math.sin(t * 2) * 3

    // left arm
    c.stroke(190, 205, 215)
    c.strokeWeight(10)

    c.line(
      cx - 45,
      cy - 5,
      cx - 72,
      cy - 35
    )

    c.fill(30, 110, 150)
    c.stroke(0, 210, 255)
    c.strokeWeight(2)

    c.ellipse(
      cx - 72,
      cy - 35,
      19,
      22
    )

    // right arm
    c.stroke(190, 205, 215)
    c.strokeWeight(10)

    c.line(
      cx + 45,
      cy - 5,
      cx + 70,
      cy - 30 + handOffset
    )

    c.fill(30, 110, 150)
    c.stroke(0, 210, 255)
    c.strokeWeight(2)

    c.ellipse(
      cx + 70,
      cy - 30 + handOffset,
      20,
      23
    )

    // --------------------------------------------------------
    // HEAD
    // --------------------------------------------------------

    val hx = cx
    val hy = cy + 72

    // head shadow
    c.fill(0, 0, 0, 100)
    c.noStroke()

    c.ellipse(
      hx + 4,
      hy - 4,
      82,
      68
    )

    // head
    c.fill(215, 225, 232)
    c.stroke(25, 55, 75)
    c.strokeWeight(3)

    c.rect(
      hx - 40,
      hy - 32,
      80,
      64
    )

    // blue forehead
    c.fill(0, 80, 130)
    c.stroke(0, 220, 255)
    c.strokeWeight(2)

    c.rect(
      hx - 25,
      hy + 12,
      50,
      12
    )

    // --------------------------------------------------------
    // EYES
    // --------------------------------------------------------

    val eyeHeight =
      if (math.sin(blink) > 0.985)
        2
      else
        11

    c.fill(5, 15, 25)
    c.noStroke()

    c.ellipse(
      hx - 16,
      hy - 2,
      13,
      eyeHeight
    )

    c.ellipse(
      hx + 16,
      hy - 2,
      13,
      eyeHeight
    )

    // eye blue glow
    c.fill(
      0,
      230,
      255,
      230
    )

    c.ellipse(
      hx - 15,
      hy - 1,
      5,
      5
    )

    c.ellipse(
      hx + 17,
      hy - 1,
      5,
      5
    )

    // --------------------------------------------------------
    // MOUTH ? TALKING ANIMATION
    // --------------------------------------------------------

    c.stroke(
      0,
      110,
      180
    )

    c.strokeWeight(2)

    if (talking) {

      val mouth =
        5 + math.abs(math.sin(t * 8)) * 8

      c.noFill()

      c.ellipse(
        hx,
        hy - 18,
        20,
        mouth
      )

    } else {

      c.line(
        hx - 9,
        hy - 18,
        hx + 9,
        hy - 18
      )
    }

    // ears
    c.fill(160, 175, 185)
    c.stroke(0, 170, 230)
    c.strokeWeight(2)

    c.ellipse(hx - 44, hy, 15, 25)
    c.ellipse(hx + 44, hy, 15, 25)

    // ear LEDs
    c.fill(
      0,
      220,
      255,
      a(130 + math.sin(t * 6) * 100)
    )

    c.noStroke()

    c.ellipse(hx - 44, hy, 6, 8)
    c.ellipse(hx + 44, hy, 6, 8)

    // antenna
    c.stroke(80, 100, 115)
    c.strokeWeight(2)

    c.line(
      hx,
      hy + 33,
      hx,
      hy + 50
    )

    c.fill(
      0,
      230,
      255,
      a(150 + math.sin(t * 5) * 100)
    )

    c.ellipse(
      hx,
      hy + 55,
      10,
      10
    )
  }

  // ==========================================================
  // RIGHT SIDE AI INFORMATION BOX
  // ==========================================================

  def aiInfo(c: CanvasDraw): Unit = {

    val x = cwidth / 2.0 + 145
    val y = 150.0
    val w = 205.0
    val h = 185.0

    // glowing shadow
    c.fill(0, 0, 0, 120)
    c.noStroke()

    c.rect(
      x + 5,
      y - 5,
      w,
      h
    )

    // blue panel
    c.fill(5, 25, 45, 245)

    c.stroke(
      0,
      190,
      255,
      a(150 + math.sin(pulse) * 80)
    )

    c.strokeWeight(3)

    c.rect(
      x,
      y,
      w,
      h
    )

    // inner border
    c.noFill()
    c.stroke(0, 100, 180, 120)
    c.strokeWeight(1)

    c.rect(
      x + 8,
      y + 8,
      w - 16,
      h - 16
    )

    // TITLE
    c.fill(255, 255, 255)
    c.text(
      "AI ROBOT INFO",
      x + 22,
      y + 155
    )

    // blue divider
    c.stroke(0, 210, 255)
    c.strokeWeight(2)

    c.line(
      x + 18,
      y + 143,
      x + w - 18,
      y + 143
    )

    // WHITE INFORMATION
    c.fill(255, 255, 255)

    c.text(
      "NAME : BLUE AI",
      x + 20,
      y + 120
    )

    c.text(
      "STATUS : ONLINE",
      x + 20,
      y + 100
    )

    c.text(
      "SYSTEM : ACTIVE",
      x + 20,
      y + 80
    )

    c.text(
      "VISION : ENABLED",
      x + 20,
      y + 60
    )

    c.text(
      "VOICE : ACTIVE",
      x + 20,
      y + 40
    )

    c.text(
      "MODE : SMART",
      x + 20,
      y + 20
    )

    // status LED
    c.fill(
      0,
      255,
      150,
      a(140 + math.sin(t * 5) * 100)
    )

    c.noStroke()

    c.ellipse(
      x + w - 22,
      y + h - 22,
      10,
      10
    )
  }

  // ==========================================================
  // ROBOT SPEECH BOX ? BLUE TEXT
  // ==========================================================

  def speech(c: CanvasDraw): Unit = {

    val x = cwidth / 2.0 - 285
    val y = 112.0

    // speech panel
    c.fill(0, 20, 40, 235)

    c.stroke(
      0,
      180,
      255,
      220
    )

    c.strokeWeight(2)

    c.rect(
      x,
      y,
      175,
      48
    )

    // BLUE TALKING TEXT
    c.fill(
      0,
      210,
      255,
      255
    )

    if (talking) {

      val phase =
        (t.toInt / 35) % 4

      if (phase == 0)
        c.text("HELLO! ?", x + 18, y + 30)

      else if (phase == 1)
        c.text("I AM BLUE AI", x + 18, y + 30)

      else if (phase == 2)
        c.text("SYSTEM ONLINE", x + 18, y + 30)

      else
        c.text("HOW CAN I HELP?", x + 12, y + 30)

    } else {

      c.text("READY...", x + 45, y + 30)
    }
  }

  // ==========================================================
  // TOP TITLE
  // ==========================================================

  def title(c: CanvasDraw): Unit = {

    c.fill(
      0,
      220,
      255,
      a(190 + math.sin(pulse) * 50)
    )

    c.text(
      "BLUE AI ? SMART ROBOT SYSTEM",
      cwidth / 2.0 - 145,
      cheight - 30
    )

    c.fill(255, 255, 255)

    c.text(
      "ADVANCED ARTIFICIAL INTELLIGENCE",
      cwidth / 2.0 - 145,
      cheight - 52
    )
  }

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

  def clickEffect(c: CanvasDraw): Unit = {

    if (clicked) {

      val r =
        10 + (math.sin(t * 6) + 1) * 15

      c.noFill()

      c.stroke(
        0,
        220,
        255,
        150
      )

      c.strokeWeight(2)

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

  // ==========================================================
  // MAIN ANIMATION LOOP
  // ==========================================================

  def drawLoop(c: CanvasDraw): Unit = {

    // animation
    t += 0.04
    scan += 2.0
    pulse += 0.08
    blink += 0.035
    bob = math.sin(t * 2.0) * 2.0

    // mouse interaction
    if (isMousePressed) {

      targetX = mouseX.toDouble
      targetY = mouseY.toDouble

      clicked = true
      waving = true
      talking = true
    }

    // wave animation
    if (waving) {

      wave += 0.25

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

    // head movement
    val wantedHead =
      clamp(
        (targetX - (cwidth / 2.0 - 85)) * 0.015,
        -8,
        8
      )

    headTurn +=
      (wantedHead - headTurn) * 0.08

    // DRAW
    background(c)
    tv(c)
    robot(c)
    aiInfo(c)
    speech(c)
    clickEffect(c)
    title(c)
  }
}

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

canvasSketch(sketch)