Code Sketch


happy nag panchimi [aLOK]
By: Mhalsakant School
Category: Art
import scala.collection.mutable.ArrayBuffer

cleari()
originBottomLeft()

// ============================================================
// NAG PANCHAMI - SNAKE GAME ERROR-FREE FIX V13.0
// ============================================================

var globalTime = 0.0
var waveAngle = 0.0
var currentStoryStage = 0 // 0: Welcome, 1: Mandir/Sheti Darshan, 2: Snake Game Play

// Game Variables
var snakeX = cwidth / 2.0
var snakeY = cheight / 2.0
var snakeDir = "RIGHT"
var score = 0
var flowerX = randomDouble(100, cwidth - 100)
var flowerY = randomDouble(100, cheight - 100)

// Nag Panchami Theme Tunes
val nagPanchamiTune = ArrayBuffer((60,300),(62,300),(65,400),(65,300),(67,400),(65,300),(62,300),(60,500),(65,300),(67,400),(69,500),(67,400),(65,400),(62,400),(60,600))
var nagIndex = 0
var nagTuneFinished = false

var audioEnabled = false
try {
  setNoteInstrument(Instrument.FLUTE)
  audioEnabled = true
} catch {
  case _: Exception => audioEnabled = false
}

def playSoundFx(note: Int, duration: Int): Unit = {
  if (audioEnabled) {
    try { playNote(note, duration) } catch { case _: Exception => }
  }
}

// Festival Sparkles
case class FestivalParticle(var x: Double, var y: Double, var vx: Double, var vy: Double, var life: java.awt.Color, var size: Double)
val festivalParticles = ArrayBuffer.empty[FestivalParticle]

def spawnFestivalParticles(x: Double, y: Double, count: Int): Unit = {
  var i = 0
  while (i < count && festivalParticles.length < 300) {
    val col = if (randomBoolean) Color(255, 255, 0) else Color(255, 140, 0)
    festivalParticles.append(FestivalParticle(x, y, randomDouble(-3.0, 3.0), randomDouble(1.0, 4.0), col, randomDouble(3.0, 7.0)))
    i += 1
  }
}

// Main Animation & Render Loop
animateWithState(0.0) { angle =>
  erasePictures()
  
  globalTime += 0.03
  waveAngle += 0.05
  
  // Update particles
  festivalParticles.filterInPlace(_.life.getAlpha > 0.0)
  festivalParticles.foreach { p =>
    p.x += p.vx
    p.y += p.vy
  }

  // Play festival tune
  if (!nagTuneFinished && audioEnabled) {
    if (nagIndex < nagPanchamiTune.length) {
      val (n, d) = nagPanchamiTune(nagIndex)
      playSoundFx(n, d)
      nagIndex += 1
    } else {
      nagTuneFinished = true
    }
  }

  // Set Background (Sky)
  setBackground(Color(20, 35, 60))

  if (currentStoryStage == 0) {
    // --- WELCOME SCREEN ---
    val titlePic = Picture.text("NAG PANCHAMI & SHREE KSHETRA UTSAV", 26)
    titlePic.setPenColor(Color(255, 215, 0))
    titlePic.setPosition(cwidth / 2.0 - 200, cheight - 100)
    draw(titlePic)

    val subPic = Picture.text("Worship Nag Devta in Sacred Fields & Play Festival Snake Game!", 14)
    subPic.setPenColor(Color(200, 230, 255))
    subPic.setPosition(cwidth / 2.0 - 210, cheight - 140)
    draw(subPic)

    var i = 0
    while (i < 12) {
      val px = cwidth / 2.0 - 150 + (i * 25.0)
      val py = cheight / 2.0 + math.sin(waveAngle + (i * 0.5)) * 40.0
      val bodyPart = Picture.circle(10.0)
      bodyPart.setFillColor(Color(34, 139, 34))
      bodyPart.setPenColor(Color(255, 215, 0))
      bodyPart.setPosition(px, py)
      draw(bodyPart)
      i += 1
    }

    val promptPic = Picture.text("Click anywhere or press Enter to Start Mandir & Snake Game", 14)
    promptPic.setPenColor(Color(255, 180, 50))
    promptPic.setPosition(cwidth / 2.0 - 220, 60)
    draw(promptPic)

  } else if (currentStoryStage == 1) {
    // --- MANDIR & SHETI SCENE ---
    val fieldBase = Picture.rect(cwidth, 120)
    fieldBase.setFillColor(Color(45, 100, 45))
    fieldBase.setPenColor(Color(60, 140, 60))
    fieldBase.setPosition(0, 0)
    draw(fieldBase)

    var f = 0
    while (f < cwidth) {
      val cropLine = Picture.line(0, 20)
      cropLine.setPenColor(Color(100, 200, 80))
      cropLine.setPenThickness(2.0)
      cropLine.setPosition(f, 20)
      draw(cropLine)
      f += 40
    }

    val mandirWall = Picture.rect(160, 100)
    mandirWall.setFillColor(Color(180, 180, 190))
    mandirWall.setPenColor(Color(220, 220, 230))
    mandirWall.setPosition(cwidth / 2.0 - 80, 60)
    draw(mandirWall)

    val shikhar = Picture.rect(100, 70)
    shikhar.setFillColor(Color(210, 180, 140))
    shikhar.setPenColor(Color(255, 215, 0))
    shikhar.setPosition(cwidth / 2.0 - 50, 160)
    draw(shikhar)

    val flag = Picture.line(0, 25)
    flag.setPenColor(Color(255, 69, 0))
    flag.setPenThickness(3.0)
    flag.setPosition(cwidth / 2.0, 230)
    draw(flag)

    val templeHeading = Picture.text("=== SHRI KSHETRA MANDIR & NAG DEVTA ===", 18)
    templeHeading.setPenColor(Color(255, 220, 100))
    templeHeading.setPosition(cwidth / 2.0 - 180, cheight - 50)
    draw(templeHeading)

    val blessingText = Picture.text("Press Enter or Click to Play Festival Snake Game!", 16)
    blessingText.setPenColor(Color(255, 255, 100))
    blessingText.setPosition(cwidth / 2.0 - 180, cheight - 90)
    draw(blessingText)

  } else {
    // --- STAGE 2: FESTIVAL SNAKE GAME PLAY SCENE ---
    
    // Update snake movement based on direction
    if (snakeDir == "RIGHT") snakeX += 4.0
    if (snakeDir == "LEFT") snakeX -= 4.0
    if (snakeDir == "UP") snakeY += 4.0
    if (snakeDir == "DOWN") snakeY -= 4.0

    // Screen wrapping / boundaries
    if (snakeX > cwidth) snakeX = 0.0
    if (snakeX < 0) snakeX = cwidth
    if (snakeY > cheight) snakeY = 0.0
    if (snakeY < 0) snakeY = cheight

    // Check collision with flower (food)
    val dist = math.hypot(snakeX - flowerX, snakeY - flowerY)
    if (dist < 22.0) {
      score += 1
      flowerX = randomDouble(50, cwidth - 50)
      flowerY = randomDouble(50, cheight - 50)
      spawnFestivalParticles(snakeX, snakeY, 15)
    }

    // Draw Flower / Offering
    val flowerPic = Picture.circle(9.0)
    flowerPic.setFillColor(Color(255, 105, 180))
    flowerPic.setPenColor(Color(255, 255, 255))
    flowerPic.setPosition(flowerX, flowerY)
    draw(flowerPic)

    // Draw Snake Head (Nag Devta)
    val snakeHead = Picture.circle(15.0)
    snakeHead.setFillColor(Color(34, 139, 34))
    snakeHead.setPenColor(Color(255, 215, 0))
    snakeHead.setPosition(snakeX, snakeY)
    draw(snakeHead)

    // Draw Score & Instructions
    val scorePic = Picture.text(s"Nag Score (Flowers Collected): $score", 16)
    scorePic.setPenColor(Color(255, 220, 100))
    scorePic.setPosition(50, cheight - 50)
    draw(scorePic)

    val controlHint = Picture.text("Use W, A, S, D or Arrow Keys / Letters to Move Snake!", 14)
    controlHint.setPenColor(Color(200, 230, 255))
    controlHint.setPosition(50, cheight - 80)
    draw(controlHint)
  }

  angle + 1.0
}

// Mouse click handler to advance stages
onMouseClick { (x, y) =>
  if (currentStoryStage == 0) {
    currentStoryStage = 1
  } else if (currentStoryStage == 1) {
    currentStoryStage = 2
    spawnFestivalParticles(cwidth / 2.0, cheight / 2.0, 30)
  }
}

// Keyboard Controls for both Stage Transition & Snake Movement (Using Char codes)
onKeyPress { k =>
  if (currentStoryStage < 2) {
    if (k == '\n' || k == '\r') {
      if (currentStoryStage == 0) {
        currentStoryStage = 1
      } else if (currentStoryStage == 1) {
        currentStoryStage = 2
        spawnFestivalParticles(cwidth / 2.0, cheight / 2.0, 30)
      }
    }
  } else {
    // Snake Direction Controls using characters (d/a/w/s or arrows)
    if (k == 'd' || k == 'D') snakeDir = "RIGHT"
    else if (k == 'a' || k == 'A') snakeDir = "LEFT"
    else if (k == 'w' || k == 'W') snakeDir = "UP"
    else if (k == 's' || k == 'S') snakeDir = "DOWN"
  }
}

println("=== NAG PANCHAMI SNAKE GAME LOADED SUCCESSFULLY ===")