Code Sketch


sniper_0718
By: Mhalsakant School
Category: Art
cleari()
setBackground(cm.darkGray)
disablePanAndZoom()

val cb = canvasBounds

var inputStr = "0"
var storedValue: Double = 0.0
var pendingOp: String = ""
var resetScreen = false

// Title Banner
val banner = Picture.text("Scala Kojo Animated Calc").withPenColor(cm.cyan)
banner.setPosition(cb.x + 40, cb.y + 450)
draw(banner)

// Screen Display Box (Black Box Container)
val boxX = cb.x + 50
val boxY = cb.y + 360
val screenBox = Picture.rectangle(290, 55).withFillColor(cm.black).withPenColor(cm.gold)
screenBox.setPosition(boxX, boxY)
draw(screenBox)

// Display text strictly locked inside the black box, starting from the left with large font
var displayPic = Picture.text(inputStr).withPenColor(cm.green)
displayPic.scale(1.5)
displayPic.setPosition(boxX + 15, boxY + 15)
draw(displayPic)

def refreshDisplay(s: String): Unit = {
  displayPic.erase()
  displayPic = Picture.text(s).withPenColor(cm.green)
  displayPic.scale(1.5)
  displayPic.setPosition(boxX + 15, boxY + 15)
  draw(displayPic)
}

def appendDigit(d: String): Unit = {
  if (inputStr == "0" || resetScreen) {
    inputStr = d
    resetScreen = false
  } else {
    if (inputStr.length < 10) {
      inputStr = inputStr + d
    }
  }
  refreshDisplay(inputStr)
}

def handleOp(op: String): Unit = {
  storedValue = inputStr.toDouble
  pendingOp = op
  resetScreen = true
}

def calculate(): Unit = {
  val currentValue = inputStr.toDouble
  val res = pendingOp match {
    case "+" => storedValue + currentValue
    case "-" => storedValue - currentValue
    case "*" => storedValue * currentValue
    case "/" => if (currentValue != 0) storedValue / currentValue else 0.0
    case _ => currentValue
  }
  inputStr = res.toString
  refreshDisplay(inputStr)
  resetScreen = true
  triggerSparkles()
}

def clearAll(): Unit = {
  inputStr = "0"
  storedValue = 0.0
  pendingOp = ""
  refreshDisplay(inputStr)
}

val startX = cb.x + 50
val startY = cb.y + 120
val w = 65
val h = 50
val gap = 10

def button(label: String, col: Int, row: Int, action: => Unit): Unit = {
  val x = startX + col * (w + gap)
  val y = startY + row * (h + gap)
  val bg = Picture.rectangle(w, h).withFillColor(cm.darkBlue).withPenColor(cm.lightGray)
  val txt = Picture.text(label).withPenColor(cm.white)
  val btn = picStackCentered(bg, txt)
  btn.setPosition(x, y)
  btn.draw()
  
  btn.onMouseClick { (_, _) =>
    action
  }
}

// Layout Calculator Grid Buttons (AC for clear)
button("7", 0, 3, appendDigit("7"))
button("8", 1, 3, appendDigit("8"))
button("9", 2, 3, appendDigit("9"))
button("/", 3, 3, handleOp("/"))

button("4", 0, 2, appendDigit("4"))
button("5", 1, 2, appendDigit("5"))
button("6", 2, 2, appendDigit("6"))
button("*", 3, 2, handleOp("*"))

button("1", 0, 1, appendDigit("1"))
button("2", 1, 1, appendDigit("2"))
button("3", 2, 1, appendDigit("3"))
button("-", 3, 1, handleOp("-"))

button("0", 0, 0, appendDigit("0"))
button("AC", 1, 0, clearAll())
button("=", 2, 0, calculate())
button("+", 3, 0, handleOp("+"))

// Ambient background floating particles
val ambientParticles = (1.to(18)).map { _ =>
  val p = Picture.circle(math.random() * 3 + 1).withFillColor(cm.gray).withNoPen
  p.setPosition(cb.x + math.random() * 350, cb.y + math.random() * 500)
  draw(p)
  p
}

// Calculation Explosion Sparkles State
var showSparkles = false
var sparkleCount = 0
val sparks = (1.to(12)).map { _ =>
  val s = Picture.circle(5).withFillColor(cm.yellow).withNoPen
  s.setPosition(boxX + 145, boxY + 28)
  s
}

def triggerSparkles(): Unit = {
  sparks.foreach { s =>
    s.setPosition(boxX + 145, boxY + 28)
    draw(s)
  }
  sparkleCount = 0
  showSparkles = true
}

// High-Performance Animation Loop
animate {
  ambientParticles.foreach { p =>
    p.translate(0, 0.5)
    val pos = p.position
    if (pos.y > cb.y + 500) {
      p.setPosition(pos.x, cb.y)
    }
  }

  if (showSparkles) {
    sparkleCount += 1
    sparks.foreach { s =>
      s.translate((math.random() - 0.5) * 8, (math.random() - 0.5) * 8)
      s.rotate(15)
    }
    if (sparkleCount > 35) {
      sparks.foreach(_.erase())
      showSparkles = false
    }
  }
}

activateCanvas()