Code Sketch


atharva ghodke
By: Mhalsakant School
Category: Programming
// ============================================================
// FUTURISTIC HOLOGRAM ROBOT - ADVANCED ANIMATION
// KOJO / SCALA
// ============================================================

cleari()
originBottomLeft()

class Sketch {

  var t = 0.0
  var bob = 0.0
  var ringAngle = 0.0
  var eyeGlow = 0.0
  var coreGlow = 0.0
  var waveAngle = 0.0
  var waving = false

  var robotX = cwidth / 2.0
  var robotY = 205.0

  var targetX = robotX
  var targetY = robotY

  var lookX = 0.0
  var lookY = 0.0

  var clicked = false
  var clickX = 0.0
  var clickY = 0.0

  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

  // ----------------------------------------------------------
  // BACKGROUND
  // ----------------------------------------------------------

  def drawBackground(c: CanvasDraw): Unit = {

    c.background(5, 10, 28)

    // Digital grid
    c.stroke(20, 75, 115, 65)
    c.strokeWeight(1)

    for (x <- 0 until cwidth.toInt by 35) {
      c.line(x, 55, x, cheight)
    }

    for (y <- 55 until cheight.toInt by 35) {
      c.line(0, y, cwidth, y)
    }

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

      val px =
        (i * 97.0 + math.sin(t + i) * 12.0) %
        cwidth

      val py =
        60.0 +
        ((i * 61.0 + t * (12 + i % 5)) %
        (cheight - 70))

      val size =
        2.0 + math.sin(t * 2.0 + i) * 1.0

      c.noStroke()
      c.fill(0, 210, 255, 150)

      c.ellipse(px, py, size, size)
    }

    // Ground glow
    c.noStroke()
    c.fill(0, 130, 220, 35)
    c.ellipse(cwidth / 2.0, 75, 360, 45)

    c.fill(0, 190, 255, 25)
    c.ellipse(cwidth / 2.0, 75, 250, 25)
  }

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

  def drawPlatform(c: CanvasDraw): Unit = {

    val cx = robotX
    val cy = 88.0

    c.noFill()
    c.stroke(0, 200, 255, 150)
    c.strokeWeight(2)

    c.ellipse(cx, cy, 190, 30)
    c.ellipse(cx, cy, 145, 22)

    c.stroke(0, 230, 255, 90)
    c.ellipse(
      cx,
      cy,
      220 + math.sin(t * 2.0) * 10.0,
      38
    )

    c.noStroke()
    c.fill(0, 190, 255, 80)
    c.ellipse(cx, cy, 90, 12)
  }

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

  def drawRings(c: CanvasDraw): Unit = {

    val cx = robotX
    val cy = robotY + bob

    c.noFill()
    c.strokeWeight(2)

    // Horizontal energy rings
    c.stroke(0, 230, 255, 130)

    c.ellipse(
      cx,
      cy + 20,
      170 + math.sin(ringAngle) * 12,
      38
    )

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

    c.ellipse(
      cx,
      cy + 20,
      135,
      30 + math.cos(ringAngle) * 8
    )

    // Orbiting energy nodes
    for (i <- 0 until 6) {

      val a = ringAngle + i * math.Pi / 3.0

      val px = cx + math.cos(a) * 83
      val py = cy + 20 + math.sin(a) * 18

      c.noStroke()
      c.fill(0, 240, 255, 230)
      c.ellipse(px, py, 7, 7)

      c.fill(0, 200, 255, 55)
      c.ellipse(px, py, 15, 15)
    }
  }

  // ----------------------------------------------------------
  // ROBOT LEGS
  // ----------------------------------------------------------

  def drawLegs(c: CanvasDraw): Unit = {

    val bx = robotX
    val by = robotY + bob

    c.stroke(120, 230, 255)
    c.strokeWeight(12)

    c.line(bx - 23, by - 35, bx - 30, by - 65)
    c.line(bx + 23, by - 35, bx + 30, by - 65)

    c.stroke(35, 130, 190)
    c.strokeWeight(5)

    c.line(bx - 30, by - 65, bx - 42, by - 75)
    c.line(bx + 30, by - 65, bx + 42, by - 75)

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

    c.ellipse(bx - 42, by - 76, 20, 8)
    c.ellipse(bx + 42, by - 76, 20, 8)

    // Knee joints
    c.fill(30, 70, 125)
    c.stroke(0, 230, 255)
    c.strokeWeight(2)

    c.ellipse(bx - 27, by - 49, 15, 15)
    c.ellipse(bx + 27, by - 49, 15, 15)
  }

  // ----------------------------------------------------------
  // ROBOT BODY AND ENERGY CORE
  // ----------------------------------------------------------

  def drawBody(c: CanvasDraw): Unit = {

    val bx = robotX
    val by = robotY + bob

    // Shoulder joints
    c.fill(20, 85, 145)
    c.stroke(0, 225, 255)
    c.strokeWeight(2)

    c.ellipse(bx - 39, by + 28, 27, 30)
    c.ellipse(bx + 39, by + 28, 27, 30)

    // Torso
    c.fill(15, 35, 72)
    c.stroke(40, 210, 255)
    c.strokeWeight(3)

    c.ellipse(bx, by + 5, 78, 88)

    // Chest armor
    c.fill(20, 70, 115)
    c.stroke(80, 230, 255)

    c.ellipse(bx, by + 12, 53, 59)

    // Energy core
    val glow =
      alpha(140 + math.sin(coreGlow) * 90)

    c.noStroke()
    c.fill(0, 200, 255, 45)
    c.ellipse(bx, by + 12, 53, 53)

    c.fill(0, 230, 255, glow)
    c.ellipse(bx, by + 12, 30, 30)

    c.fill(210, 255, 255, 240)
    c.ellipse(bx, by + 12, 13, 13)

    // Chest circuits
    c.stroke(0, 230, 255, 200)
    c.strokeWeight(2)

    c.line(bx - 20, by + 28, bx - 10, by + 20)
    c.line(bx + 20, by + 28, bx + 10, by + 20)
    c.line(bx - 19, by - 8, bx - 10, by - 3)
    c.line(bx + 19, by - 8, bx + 10, by - 3)

    // Core indicators
    c.noStroke()
    c.fill(110, 255, 255)

    for (i <- 0 until 3) {
      c.ellipse(bx - 9 + i * 9, by - 20, 4, 4)
    }
  }

  // ----------------------------------------------------------
  // ANIMATED ARMS
  // ----------------------------------------------------------

  def drawArms(c: CanvasDraw): Unit = {

    val bx = robotX
    val by = robotY + bob

    val swing =
      if (waving) math.sin(waveAngle) * 28
      else math.sin(t * 2.0) * 5

    // Left arm
    c.stroke(65, 190, 240)
    c.strokeWeight(11)

    c.line(bx - 38, by + 28, bx - 56, by + 3)
    c.line(bx - 56, by + 3, bx - 65, by - 17)

    c.fill(20, 90, 155)
    c.stroke(0, 225, 255)
    c.strokeWeight(2)

    c.ellipse(bx - 56, by + 3, 17, 17)
    c.ellipse(bx - 65, by - 17, 18, 18)

    // Right arm with animated hand
    val handX = bx + 70
    val handY = by + 7 + swing

    c.stroke(65, 190, 240)
    c.strokeWeight(11)

    c.line(bx + 38, by + 28, bx + 56, by + 4)
    c.line(bx + 56, by + 4, handX, handY)

    c.fill(20, 90, 155)
    c.stroke(0, 225, 255)
    c.strokeWeight(2)

    c.ellipse(bx + 56, by + 4, 17, 17)

    c.fill(100, 245, 255, 220)
    c.ellipse(handX, handY, 21, 21)

    // Finger rays
    c.stroke(120, 255, 255)
    c.strokeWeight(2)

    for (i <- 0 until 3) {
      c.line(
        handX + 3,
        handY + 2,
        handX + 13,
        handY + 5 + i * 5
      )
    }
  }

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

  def drawHead(c: CanvasDraw): Unit = {

    val hx = robotX
    val hy = robotY + bob + 65

    // Neck
    c.fill(20, 80, 130)
    c.stroke(0, 220, 255)
    c.strokeWeight(2)

    c.rect(hx - 12, hy - 34, 24, 15)

    // Head shadow
    c.noStroke()
    c.fill(0, 150, 255, 35)
    c.ellipse(hx, hy, 94, 76)

    // Main head
    c.fill(15, 35, 68)
    c.stroke(70, 220, 255)
    c.strokeWeight(3)

    c.rect(hx - 39, hy - 29, 78, 58)

    // Face display
    c.fill(5, 20, 42)
    c.stroke(0, 130, 210)

    c.rect(hx - 31, hy - 21, 62, 41)

    // Eyes
    val eye = alpha(170 + math.sin(eyeGlow) * 75)

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

    c.ellipse(hx - 15 + lookX, hy + 5 + lookY, 23, 23)
    c.ellipse(hx + 15 + lookX, hy + 5 + lookY, 23, 23)

    c.fill(80, 255, 255, eye)

    c.ellipse(hx - 15 + lookX, hy + 5 + lookY, 11, 11)
    c.ellipse(hx + 15 + lookX, hy + 5 + lookY, 11, 11)

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

    c.ellipse(hx - 15 + lookX, hy + 5 + lookY, 4, 4)
    c.ellipse(hx + 15 + lookX, hy + 5 + lookY, 4, 4)

    // Mouth
    c.stroke(0, 220, 255)
    c.strokeWeight(2)

    c.line(hx - 10, hy - 10, hx + 10, hy - 10)

    // Antenna
    c.stroke(80, 210, 255)
    c.strokeWeight(3)

    c.line(hx, hy + 29, hx, hy + 43)

    c.noStroke()
    c.fill(0, 240, 255, eye)
    c.ellipse(hx, hy + 47, 10, 10)

    c.fill(0, 230, 255, 45)
    c.ellipse(hx, hy + 47, 21, 21)

    // Side ear panels
    c.fill(20, 100, 155)
    c.stroke(0, 220, 255)
    c.strokeWeight(2)

    c.rect(hx - 46, hy - 12, 8, 24)
    c.rect(hx + 38, hy - 12, 8, 24)

    c.noStroke()
    c.fill(120, 255, 255)

    c.ellipse(hx - 42, hy, 4, 10)
    c.ellipse(hx + 42, hy, 4, 10)
  }

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

  def drawHUD(c: CanvasDraw): Unit = {

    val x = 30.0
    val y = cheight - 55.0

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

    c.text("HOLOGRAM SYSTEM", x, y)
    c.text("ROBOT STATUS: ONLINE", x, y - 22)

    c.fill(100, 220, 255, 160)

    for (i <- 0 until 12) {
      val h = 5 + ((i * 7 + t.toInt) % 18)
      c.rect(x + i * 12, y - 48, 6, h)
    }

    c.fill(0, 220, 255, 200)
    c.text("TOUCH ROBOT TO ACTIVATE", cwidth / 2.0 - 100, 25)
  }

  // ----------------------------------------------------------
  // INTERACTION RING
  // ----------------------------------------------------------

  def drawClickEffect(c: CanvasDraw): Unit = {

    if (clicked) {

      val radius = 15 + (t * 18 % 55)

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

      c.ellipse(clickX, clickY, radius * 2, radius * 2)

      c.stroke(120, 80, 255, 130)
      c.ellipse(
        clickX,
        clickY,
        radius * 1.4,
        radius * 1.4
      )

      if (radius > 65) clicked = false
    }
  }

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

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

  def drawLoop(c: CanvasDraw): Unit = {

    t += 0.04
    ringAngle += 0.045
    eyeGlow += 0.08
    coreGlow += 0.06

    drawBackground(c)

    // Read interaction
    if (isMousePressed) {

      targetX = clamp(
        mouseX.toDouble,
        cwidth / 2.0 - 180,
        cwidth / 2.0 + 180
      )

      targetY = clamp(
        mouseY.toDouble,
        110,
        340
      )

      clickX = targetX
      clickY = targetY

      clicked = true
      waving = true
    }

    // Head tracking
    lookX = clamp((targetX - robotX) * 0.035, -5, 5)
    lookY = clamp((targetY - robotY) * 0.025, -4, 4)

    // Floating movement
    bob = math.sin(t * 2.0) * 3.0

    // Wave movement
    if (waving) {
      waveAngle += 0.22

      if (waveAngle > 12.0) {
        waving = false
        waveAngle = 0
      }
    }

    // Draw from back to front
    drawPlatform(c)
    drawRings(c)
    drawLegs(c)
    drawBody(c)
    drawArms(c)
    drawHead(c)
    drawClickEffect(c)
    drawHUD(c)
  }
}

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

val sketch = new Sketch
canvasSketch(sketch)