Code Sketch


Siddhi sabale
By: Mhalsakant School
Category: Art
cleari()
originBottomLeft()

// ============================================================
// ISRO MARS MISSION - ULTIMATE EDITION WITH MOON & LANDER
// White + Green Robot + Indian Flag + Vikram Lander + Footprints
// ============================================================

var robotX = 180.0
var robotY = 145.0
var robotWalk = 0.0
var robotBob = 0.0
var robotGlow = 0.0
var robotHeadTurn = 0.0
var robotArmWave = 0.0
var robotTime = 0.0
var robotMoving = true
var robotFacing = 1.0

// ------------------------------------------------------------
// Meteor / Shooting Star Variables (??????? ????)
// ------------------------------------------------------------
var meteorX = cwidth + 50.0
var meteorY = cheight - 50.0
var meteorActive = false
var meteorTimer = 0.0

// ------------------------------------------------------------
// Martian Footprints Array (???????? ???)
// ------------------------------------------------------------
val maxFootprints = 16
val fpX = Array.fill(maxFootprints)(-100.0)
val fpY = Array.fill(maxFootprints)(140.0)
var fpIndex = 0
var lastStepX = robotX

// ------------------------------------------------------------
// Background Dust & Space Particles
// ------------------------------------------------------------
val particleCount = 70
val particleX = Array.fill(particleCount)(randomDouble(0, cwidth))
val particleY = Array.fill(particleCount)(randomDouble(145, cheight))
val particleSpeed = Array.fill(particleCount)(randomDouble(0.15, 0.6))

// ------------------------------------------------------------
// Robot Colors
// ------------------------------------------------------------
val whiteRobot = cm.rgb(245, 248, 250)
val whiteShadow = cm.rgb(190, 200, 205)
val greenMain = cm.rgb(0, 210, 80)
val greenDark = cm.rgb(0, 105, 45)
val greenGlow = cm.rgb(40, 255, 120)
val blackScreen = cm.rgb(5, 8, 18)

// ------------------------------------------------------------
// UPDATE LOGIC
// ------------------------------------------------------------
def updateRobot() {
  robotTime += 0.018
  robotWalk += 0.09
  robotGlow += 0.08

  // Shooting Star Logic (??????? ????)
  meteorTimer += 0.018
  if (!meteorActive && meteorTimer > 3.5) {
    meteorActive = true
    meteorX = randomDouble(cwidth * 0.4, cwidth + 50)
    meteorY = randomDouble(cheight - 80, cheight + 20)
    meteorTimer = 0.0
  }

  if (meteorActive) {
    meteorX -= 9.0
    meteorY -= 5.5
    if (meteorY < 180 || meteorX < -50) {
      meteorActive = false
    }
  }

  if (robotMoving) {
    robotX += 0.55 * robotFacing

    // Footprint Creation (???????? ??? ??????)
    if (math.abs(robotX - lastStepX) > 22.0) {
      fpX(fpIndex) = robotX - (15.0 * robotFacing)
      fpY(fpIndex) = 142.0 + randomDouble(-2, 2)
      fpIndex = (fpIndex + 1) % maxFootprints
      lastStepX = robotX
    }

    // Smooth walking bob
    robotBob = math.sin(robotWalk * 2.0) * 3.5
    robotArmWave = math.sin(robotWalk) * 22.0
    robotHeadTurn = math.sin(robotTime * 1.5) * 3.0

    // Screen Boundary
    if (robotX > cwidth - 90) robotFacing = -1.0
    if (robotX < 90) robotFacing = 1.0
  } else {
    robotBob = math.sin(robotTime * 2.0) * 2.0
    robotArmWave = math.sin(robotTime) * 5.0
  }

  // Floating Dust Particles
  for (i <- 0 until particleCount) {
    particleY(i) += particleSpeed(i)
    if (particleY(i) > cheight) {
      particleY(i) = 145
      particleX(i) = randomDouble(0, cwidth)
    }
  }
}

// ============================================================
// VIKRAM LANDER (?????? ????)
// ============================================================
def drawVikramLander(canvas: CanvasDraw, lx: Double, ly: Double) {
  // Lander Legs
  canvas.stroke(180, 180, 190)
  canvas.strokeWeight(3.0)
  canvas.line(lx - 25, ly, lx - 45, ly - 22)
  canvas.line(lx + 25, ly, lx + 45, ly - 22)
  canvas.line(lx - 12, ly, lx - 20, ly - 22)
  canvas.line(lx + 12, ly, lx + 20, ly - 22)

  // Landing Pads
  canvas.fill(120, 120, 130)
  canvas.noStroke()
  canvas.ellipse(lx - 45, ly - 22, 12, 5)
  canvas.ellipse(lx + 45, ly - 22, 12, 5)

  // Main Body (Gold Thermal Foil)
  canvas.fill(220, 165, 30)
  canvas.stroke(180, 130, 20)
  canvas.strokeWeight(1.5)
  canvas.rect(lx - 28, ly, 56, 32)

  // Top Deck
  canvas.fill(190, 140, 20)
  canvas.rect(lx - 20, ly + 32, 40, 14)

  // Solar Panels (Blue)
  canvas.fill(20, 70, 160)
  canvas.stroke(40, 100, 200)
  canvas.strokeWeight(1)
  canvas.rect(lx - 48, ly + 6, 18, 26)
  canvas.rect(lx + 30, ly + 6, 18, 26)

  // Dish Antenna
  canvas.fill(210, 215, 220)
  canvas.noStroke()
  canvas.ellipse(lx, ly + 52, 16, 10)
  canvas.stroke(200, 200, 210)
  canvas.strokeWeight(2)
  canvas.line(lx, ly + 46, lx, ly + 52)

  // ISRO Tricolor Badge
  canvas.fill(255, 153, 51); canvas.noStroke(); canvas.rect(lx - 10, ly + 20, 20, 3)
  canvas.fill(255, 255, 255); canvas.rect(lx - 10, ly + 17, 20, 3)
  canvas.fill(19, 136, 8); canvas.rect(lx - 10, ly + 14, 20, 3)
}

// ============================================================
// INDIAN TRICOLOR FLAG (??????? ??????)
// ============================================================
def drawIndianFlag(canvas: CanvasDraw, fx: Double, fy: Double) {
  // Flag Pole
  canvas.stroke(210, 215, 220)
  canvas.strokeWeight(3.5)
  canvas.line(fx, fy, fx, fy + 80)

  // Top Golden Sphere
  canvas.fill(255, 215, 0)
  canvas.noStroke()
  canvas.ellipse(fx, fy + 81, 7, 7)

  // Dynamic Waving Effect
  val wave = math.sin(robotTime * 4.0) * 3.0

  // Saffron Stripe
  canvas.fill(255, 153, 51)
  canvas.rect(fx, fy + 58 + wave, 44, 11)

  // White Stripe
  canvas.fill(255, 255, 255)
  canvas.rect(fx, fy + 47 + wave, 44, 11)

  // Ashoka Chakra (24 Spokes Representation)
  canvas.stroke(0, 0, 128)
  canvas.strokeWeight(1.2)
  canvas.ellipse(fx + 22, fy + 52.5 + wave, 7.5, 7.5)

  // Green Stripe
  canvas.fill(19, 136, 8)
  canvas.noStroke()
  canvas.rect(fx, fy + 36 + wave, 44, 11)
}

// ============================================================
// BACKGROUND: MARS LANDSCAPE WITH MOON & METEOR
// ============================================================
def drawRobotBackground(canvas: CanvasDraw) {
  // Atmospheric Sky
  canvas.fill(20, 5, 12)
  canvas.noStroke()
  canvas.rect(0, 0, cwidth, cheight)

  canvas.fill(80, 25, 20)
  canvas.rect(0, 0, cwidth, 180)

  // Stars
  canvas.fill(255, 230, 220)
  for (i <- 0 until 40) {
    val sx = (i * 37) % cwidth
    val sy = 160 + ((i * 53) % (cheight - 160))
    canvas.ellipse(sx, sy, 2, 2)
  }

  // Shooting Star (??????? ????)
  if (meteorActive) {
    canvas.stroke(255, 240, 180, 220)
    canvas.strokeWeight(2.5)
    canvas.line(meteorX, meteorY, meteorX + 35, meteorY + 22)

    canvas.fill(255, 255, 255)
    canvas.noStroke()
    canvas.ellipse(meteorX, meteorY, 4, 4)
  }

  // Moon (?????)
  val mx = cwidth - 130
  val my = cheight - 100

  canvas.fill(255, 230, 200, 30); canvas.ellipse(mx, my, 110, 110)
  canvas.fill(255, 240, 220, 60); canvas.ellipse(mx, my, 85, 85)
  canvas.fill(240, 235, 220); canvas.ellipse(mx, my, 65, 65)

  // Moon Craters
  canvas.fill(200, 195, 180)
  canvas.ellipse(mx - 10, my + 8, 14, 12)
  canvas.ellipse(mx + 12, my - 10, 18, 15)
  canvas.ellipse(mx + 5, my + 15, 10, 10)

  // Distant Earth
  canvas.fill(70, 130, 200, 180)
  canvas.ellipse(100, cheight - 70, 20, 20)

  // Distant Mountains
  canvas.fill(90, 30, 25)
  canvas.ellipse(100, 145, 320, 120)
  canvas.ellipse(350, 145, 450, 160)
  canvas.ellipse(650, 145, 380, 140)

  // Vikram Lander In Background
  drawVikramLander(canvas, 130, 155)

  // Mid-ground Mountains
  canvas.fill(130, 45, 30)
  canvas.ellipse(220, 145, 280, 100)
  canvas.ellipse(550, 145, 320, 110)

  // Mars Ground Surface
  canvas.fill(160, 55, 35)
  canvas.rect(0, 0, cwidth, 145)

  // Planted Indian Flag
  drawIndianFlag(canvas, 210, 145)

  // Craters & Rocks
  canvas.fill(120, 40, 25)
  canvas.ellipse(80, 60, 90, 25)
  canvas.ellipse(340, 40, 130, 30)
  canvas.ellipse(620, 80, 110, 28)

  // Draw Martian Footprints (???????? ???)
  canvas.fill(100, 30, 20, 160)
  canvas.noStroke()
  for (i <- 0 until maxFootprints) {
    if (fpX(i) > 0) {
      canvas.ellipse(fpX(i), fpY(i), 14, 6)
    }
  }

  // Ground Texture Lines
  canvas.stroke(180, 70, 45)
  canvas.strokeWeight(1.0)
  for (i <- 0 until 8) {
    canvas.line(0, 15 + i * 16, cwidth, 15 + i * 16)
  }

  // Floating Dust
  canvas.noStroke()
  for (i <- 0 until particleCount) {
    val glow = (math.sin(robotTime * 3 + i) * 2 + 3).toFloat
    canvas.fill(255, 140, 90, 160)
    canvas.ellipse(particleX(i), particleY(i), glow, glow)
  }
}

// ============================================================
// ROBOT SHADOW
// ============================================================
def drawRobotShadow(canvas: CanvasDraw) {
  canvas.fill(30, 10, 10, 120)
  canvas.noStroke()
  canvas.ellipse(robotX, 145, 125, 22)
}

// ============================================================
// ROBOT PARTS (FOOT, LEG, ARM, BODY)
// ============================================================
def drawRobotFoot(canvas: CanvasDraw, px: Double, py: Double, angle: Double) {
  canvas.pushMatrix()
  canvas.translate(px, py)
  canvas.rotate(angle)

  canvas.fill(0, 255, 100, 35); canvas.noStroke(); canvas.ellipse(0, 0, 58, 28)
  canvas.fill(whiteRobot); canvas.stroke(whiteShadow); canvas.strokeWeight(2.0)
  canvas.ellipse(0, 0, 60, 32)
  canvas.fill(greenMain); canvas.noStroke(); canvas.rect(-25, -5, 50, 8)
  canvas.fill(220, 225, 230); canvas.ellipse(18, 3, 25, 18)

  canvas.popMatrix()
}

def drawRobotLeg(canvas: CanvasDraw, px: Double, py: Double, legAngle: Double) {
  canvas.pushMatrix()
  canvas.translate(px, py)
  canvas.rotate(legAngle)

  canvas.fill(whiteRobot); canvas.stroke(whiteShadow); canvas.strokeWeight(2.0)
  canvas.rect(-13, -45, 26, 48)
  canvas.fill(greenMain); canvas.stroke(greenGlow); canvas.strokeWeight(1.5)
  canvas.ellipse(0, -48, 22, 22)
  canvas.fill(whiteRobot); canvas.stroke(whiteShadow); canvas.strokeWeight(2.0)
  canvas.rect(-15, -92, 30, 45)
  canvas.fill(greenMain); canvas.noStroke(); canvas.rect(-15, -88, 7, 35)

  canvas.popMatrix()
}

def drawRobotArm(canvas: CanvasDraw, px: Double, py: Double, armAngle: Double, flip: Boolean) {
  canvas.pushMatrix()
  canvas.translate(px, py)
  if (flip) canvas.scale(-1, 1)
  canvas.rotate(armAngle)

  canvas.fill(greenMain); canvas.stroke(greenGlow); canvas.strokeWeight(2); canvas.ellipse(0, 0, 30, 30)
  canvas.fill(whiteRobot); canvas.stroke(whiteShadow); canvas.strokeWeight(2); canvas.rect(-12, -48, 24, 48)
  canvas.fill(greenMain); canvas.noStroke(); canvas.ellipse(0, -50, 19, 19)
  canvas.fill(whiteRobot); canvas.stroke(whiteShadow); canvas.strokeWeight(2); canvas.rect(-11, -92, 22, 42)
  canvas.fill(greenMain); canvas.noStroke(); canvas.rect(-11, -84, 6, 25)
  canvas.fill(whiteRobot); canvas.stroke(whiteShadow); canvas.strokeWeight(2); canvas.ellipse(0, -101, 25, 22)
  canvas.fill(greenMain); canvas.noStroke(); canvas.ellipse(0, -103, 13, 10)

  canvas.popMatrix()
}

def drawRobotBody(canvas: CanvasDraw) {
  val bx = robotX
  val by = robotY + robotBob

  canvas.fill(0, 255, 100, 25); canvas.noStroke(); canvas.ellipse(bx, by + 65, 105, 125)
  canvas.fill(whiteRobot); canvas.stroke(whiteShadow); canvas.strokeWeight(2.5); canvas.rect(bx - 48, by + 20, 96, 105)
  canvas.fill(greenMain); canvas.noStroke(); canvas.rect(bx - 48, by + 28, 96, 13)

  // Reactor Core
  canvas.fill(235, 240, 242); canvas.stroke(180, 190, 195); canvas.strokeWeight(1.5); canvas.ellipse(bx, by + 90, 38, 38)
  val reactorGlow = (math.sin(robotGlow * 2) * 5 + 18).toFloat
  canvas.fill(0, 255, 100, 60); canvas.noStroke(); canvas.ellipse(bx, by + 90, 38 + reactorGlow, 38 + reactorGlow)
  canvas.fill(0, 220, 80); canvas.ellipse(bx, by + 90, 18, 18)
  canvas.fill(220, 255, 230); canvas.ellipse(bx - 4, by + 94, 6, 6)

  // ISRO Branding
  canvas.fill(20, 30, 30); canvas.text("ISRO", bx - 18, by + 115)
  canvas.fill(greenMain); canvas.noStroke(); canvas.rect(bx - 38, by + 15, 76, 15)
  canvas.fill(whiteRobot); canvas.stroke(whiteShadow); canvas.strokeWeight(2); canvas.ellipse(bx, by + 10, 35, 22)
}

// ============================================================
// ROBOT HEAD WITH BLINKING ANTENNA (?????? ???????)
// ============================================================
def drawRobotHead(canvas: CanvasDraw) {
  val hx = robotX + robotHeadTurn
  val hy = robotY + robotBob + 170

  // ----------------------------------------------------------
  // SIGNAL ANTENNA WITH BLINKING BEACON (??????)
  // ----------------------------------------------------------
  canvas.stroke(180, 190, 200)
  canvas.strokeWeight(2.5)
  canvas.line(hx, hy + 60, hx, hy + 88)

  val blink = math.sin(robotTime * 12.0)
  if (blink > 0) {
    canvas.fill(255, 40, 40, 100); canvas.noStroke(); canvas.ellipse(hx, hy + 88, 18, 18)
    canvas.fill(255, 50, 50); canvas.ellipse(hx, hy + 88, 9, 9)
  } else {
    canvas.fill(40, 255, 120, 100); canvas.noStroke(); canvas.ellipse(hx, hy + 88, 18, 18)
    canvas.fill(0, 255, 100); canvas.ellipse(hx, hy + 88, 9, 9)
  }

  // Head Base
  canvas.fill(0, 255, 120, 25); canvas.noStroke(); canvas.ellipse(hx, hy, 100, 75)
  canvas.fill(greenDark); canvas.stroke(greenMain); canvas.strokeWeight(2); canvas.rect(hx - 15, hy - 43, 30, 25)
  canvas.fill(whiteRobot); canvas.stroke(whiteShadow); canvas.strokeWeight(2.5); canvas.rect(hx - 45, hy - 5, 90, 65)

  // Face Screen & LED Eyes
  canvas.fill(blackScreen); canvas.stroke(20, 40, 50); canvas.strokeWeight(3); canvas.rect(hx - 35, hy + 5, 70, 42)
  canvas.fill(greenMain); canvas.stroke(greenGlow); canvas.strokeWeight(2); canvas.ellipse(hx + 45, hy + 28, 17, 30)

  val eyeMove = math.sin(robotTime * 2) * 2.0
  canvas.fill(40, 180, 255); canvas.ellipse(hx - 17, hy + 28 + eyeMove, 7, 7); canvas.ellipse(hx + 17, hy + 28 + eyeMove, 7, 7)
  canvas.stroke(40, 180, 255); canvas.strokeWeight(2); canvas.line(hx - 15, hy + 15, hx + 15, hy + 15)

  for (i <- 0 until 5) {
    canvas.line(hx - 25 + i * 12, hy + 48, hx - 20 + i * 12, hy + 48)
  }
}

// ============================================================
// MAIN DRAW
// ============================================================
def drawFuturisticRobot(canvas: CanvasDraw) {
  val by = robotY + robotBob

  drawRobotArm(canvas, robotX - 48, by + 105, robotArmWave, false)
  drawRobotArm(canvas, robotX + 48, by + 105, -robotArmWave, true)

  val leftLegAngle = math.sin(robotWalk) * 15.0
  val rightLegAngle = -math.sin(robotWalk) * 15.0

  drawRobotLeg(canvas, robotX - 23, by + 10, leftLegAngle)
  drawRobotLeg(canvas, robotX + 23, by + 10, rightLegAngle)

  drawRobotFoot(canvas, robotX - 30 + math.sin(robotWalk) * 8, 150, leftLegAngle)
  drawRobotFoot(canvas, robotX + 30 - math.sin(robotWalk) * 8, 150, rightLegAngle)

  drawRobotBody(canvas)
  drawRobotHead(canvas)
}

def drawRobotHUD(canvas: CanvasDraw) {
  canvas.fill(255, 220, 200)
  canvas.text("ISRO MARS EXPLORER MISSION", 25, cheight - 30)
  canvas.fill(0, 255, 120)
  canvas.text("SYSTEM : ONLINE | VIKRAM LANDER : LINKED", 25, cheight - 55)

  // Energy HUD
  canvas.fill(30, 40, 45); canvas.stroke(0, 255, 120); canvas.strokeWeight(2); canvas.rect(cwidth - 190, cheight - 65, 150, 18)
  canvas.fill(0, 230, 90); canvas.rect(cwidth - 186, cheight - 61, 135, 10)
  canvas.fill(255, 255, 255); canvas.text("ENERGY 90%", cwidth - 180, cheight - 72)
}

def viewRobot(canvas: CanvasDraw) {
  canvas.fill(0, 0, 0); canvas.noStroke(); canvas.rect(0, 0, cwidth, cheight)

  drawRobotBackground(canvas)
  drawRobotShadow(canvas)
  drawFuturisticRobot(canvas)
  drawRobotHUD(canvas)
}

// ============================================================
// START ANIMATION
// ============================================================
animateWithCanvasDraw { canvas =>
  updateRobot()
  viewRobot(canvas)
}