Code Sketch
Bixuu02
Category: Programming
// ============================================================
// RAKSHABANDHAN ANIMATED DELIVERY MISSION GAME
// SCALA SCRIPT FOR KOJO / SCALA CANVAS
// ============================================================
cleari()
originBottomLeft()
// ============================================================
// GAME STATES & ANIMATION VARIABLES
// 0 = Letter Order
// 1 = Avatar Selection (Woman / Man)
// 2 = Rakhi Creation (Shapes + Thread)
// 3 = Interactive Delivery Animation Scene
// 4 = Final Mission Completion Screen
// ============================================================
var screen = 0
var selectedAvatar = "MAN"
var selectedShape = ""
var threadAttached = false
// Delivery Animation State Variables
var carX = -120.0
var carY = 100.0
var deliveryManX = 0.0
var deliveryManY = 0.0
var womanDoorX = 0.0
var isDoorOpen = false
var hasGivenBox = false
// Delivery Sub-states:
// 0 = Car driving to house
// 1 = Delivery man walking to door
// 2 = Pressing doorbell & Woman opens door
// 3 = Handing over Rakhi Gift Box & Dialogue
// 4 = Animation complete (Show continue button)
var deliverySubState = 0
var animationTimer = 0
class Star(val x: Double, val y: Double, val size: Double) {
var phase = randomDouble(6.28)
def step() { phase += 0.04 }
def view(canvas: CanvasDraw) {
val brightness = 150 + (math.sin(phase) * 80).toInt
canvas.noStroke()
canvas.fill(brightness, brightness, 255, 200)
canvas.ellipse(x, y, size, size)
}
}
val stars = ArrayBuffer.empty[Star]
for (i <- 0 until 60) {
stars.append(new Star(randomDouble(cwidth), randomDouble(cheight), 1.0 + randomDouble(3.0)))
}
// ============================================================
// DRAW DETAILED AVATARS (WOMAN & MAN)
// ============================================================
def drawDetailedAvatar(canvas: CanvasDraw, x: Double, y: Double, gender: String, scale: Double) {
canvas.noStroke()
if (gender == "WOMAN") {
// Hair (Back)
canvas.fill(30, 20, 15)
canvas.ellipse(x, y + 20 * scale, 75 * scale, 85 * scale)
// Face
canvas.fill(255, 220, 180)
canvas.ellipse(x, y + 25 * scale, 55 * scale, 60 * scale)
// Traditional Saree & Jewelry
canvas.fill(210, 30, 90) // Pink/Red Saree
canvas.rect(x - 30 * scale, y - 60 * scale, 60 * scale, 70 * scale)
canvas.fill(255, 215, 0) // Gold Pallu & Jewelry
canvas.line(x - 30 * scale, y - 60 * scale, x + 20 * scale, y + 5 * scale)
canvas.ellipse(x - 30 * scale, y + 25 * scale, 10 * scale, 12 * scale) // Earring Left
canvas.ellipse(x + 30 * scale, y + 25 * scale, 10 * scale, 12 * scale) // Earring Right
// Bindi
canvas.fill(220, 0, 0)
canvas.ellipse(x, y + 33 * scale, 8 * scale, 8 * scale)
} else {
// Feta / Cap
canvas.fill(230, 100, 30)
canvas.ellipse(x, y + 45 * scale, 65 * scale, 35 * scale)
// Face
canvas.fill(255, 220, 180)
canvas.ellipse(x, y + 20 * scale, 55 * scale, 55 * scale)
// Kurta & Vest
canvas.fill(240, 240, 240)
canvas.rect(x - 30 * scale, y - 60 * scale, 60 * scale, 70 * scale)
canvas.fill(40, 90, 180)
canvas.rect(x - 25 * scale, y - 60 * scale, 50 * scale, 60 * scale)
}
// Eyes & Smile
canvas.fill(0, 0, 0)
canvas.ellipse(x - 12 * scale, y + 22 * scale, 6 * scale, 8 * scale)
canvas.ellipse(x + 12 * scale, y + 22 * scale, 6 * scale, 8 * scale)
canvas.stroke(180, 50, 50)
canvas.strokeWeight(2 * scale)
canvas.line(x - 10 * scale, y + 8 * scale, x + 10 * scale, y + 8 * scale)
}
// ============================================================
// DETAILED CAR DRAWING
// ============================================================
def drawDetailedCar(canvas: CanvasDraw, x: Double, y: Double) {
// Car Body Shadow
canvas.noStroke()
canvas.fill(50, 50, 50, 100)
canvas.ellipse(x + 75, y - 5, 160, 20)
// Main Body
canvas.fill(220, 30, 30)
canvas.rect(x, y + 10, 150, 45)
canvas.rect(x + 30, y + 55, 85, 35)
// Windows (Glass Details)
canvas.fill(180, 220, 255)
canvas.rect(x + 35, y + 58, 35, 28)
canvas.rect(x + 75, y + 58, 35, 28)
// Headlights & Taillights
canvas.fill(255, 230, 0) // Front Light
canvas.rect(x + 145, y + 25, 8, 15)
canvas.fill(180, 0, 0) // Tail Light
canvas.rect(x - 3, y + 25, 6, 15)
// Side Door Handles & Stripes
canvas.stroke(255, 255, 255)
canvas.strokeWeight(2)
canvas.line(x, y + 35, x + 150, y + 35)
canvas.fill(50, 50, 50)
canvas.rect(x + 55, y + 42, 10, 4)
canvas.rect(x + 95, y + 42, 10, 4)
// Detailed Wheels (Tires + Alloys)
canvas.noStroke()
val wheelPositions = Array(x + 35, x + 115)
for (wx <- wheelPositions) {
canvas.fill(20, 20, 20)
canvas.ellipse(wx, y + 8, 36, 36) // Outer Tire
canvas.fill(200, 200, 200)
canvas.ellipse(wx, y + 8, 20, 20) // Alloy Rim
canvas.fill(50, 50, 50)
canvas.ellipse(wx, y + 8, 8, 8) // Center
}
}
// ============================================================
// DRAW RAKHI DESIGN
// ============================================================
def drawRakhi(canvas: CanvasDraw, x: Double, y: Double, shape: String, showThread: Boolean) {
if (showThread) {
canvas.stroke(220, 30, 30)
canvas.strokeWeight(10)
canvas.line(x - 160, y, x + 160, y)
canvas.stroke(255, 215, 0)
canvas.strokeWeight(4)
canvas.line(x - 160, y, x + 160, y)
}
canvas.noStroke()
canvas.fill(255, 215, 0) // Gold Base
canvas.ellipse(x, y, 95, 95)
canvas.fill(220, 20, 60)
if (shape == "CIRCLE") {
canvas.ellipse(x, y, 65, 65)
canvas.fill(255, 255, 255)
canvas.ellipse(x, y, 35, 35)
} else if (shape == "TRIANGLE") {
canvas.rect(x - 28, y - 25, 56, 56)
} else if (shape == "STAR") {
canvas.ellipse(x, y, 75, 35)
canvas.ellipse(x, y, 35, 75)
canvas.fill(255, 215, 0)
canvas.ellipse(x, y, 30, 30)
}
}
// ============================================================
// DELIVERY ANIMATION SCENE
// ============================================================
def drawDeliveryAnimationScene(canvas: CanvasDraw) {
canvas.background(135, 206, 235) // Sky
// Road & Environment
canvas.noStroke()
canvas.fill(40, 160, 60)
canvas.rect(0, 0, cwidth, 160)
canvas.fill(70, 70, 75)
canvas.rect(0, 80, cwidth, 70) // Road
canvas.fill(255, 255, 255)
for (i <- 0 until 10) {
canvas.rect(i * 70, 110, 40, 8)
}
// House at Gokuldham
val houseX = cwidth - 190.0
val houseY = 140.0
canvas.fill(255, 230, 180) // Wall
canvas.rect(houseX, houseY, 160, 130)
canvas.fill(180, 50, 40) // Roof
canvas.rect(houseX - 10, houseY + 130, 180, 45)
// Doorway
canvas.fill(80, 40, 20)
canvas.rect(houseX + 60, houseY, 50, 80) // Open Door Frame
// Doorbell Switch
canvas.fill(220, 220, 220)
canvas.rect(houseX + 45, houseY + 45, 8, 12)
canvas.fill(200, 30, 30)
canvas.ellipse(houseX + 49, houseY + 51, 4, 4)
// Gokuldham Title Board
canvas.fill(0, 100, 180)
canvas.rect(houseX + 15, houseY + 100, 130, 25)
canvas.fill(255, 255, 255)
canvas.text("GOKULDHAM", houseX + 30, houseY + 107)
// Draw Detailed Car
drawDetailedCar(canvas, carX, carY)
// Woman Appearing from Door
if (isDoorOpen) {
drawDetailedAvatar(canvas, houseX + 85, houseY + 20, "WOMAN", 0.55)
}
// Delivery Person
if (deliverySubState >= 1) {
drawDetailedAvatar(canvas, deliveryManX, deliveryManY, selectedAvatar, 0.55)
// Delivery Box (Holding in Hand or Handed over)
if (!hasGivenBox) {
canvas.fill(200, 140, 60)
canvas.rect(deliveryManX + 10, deliveryManY, 22, 18) // Box in hands
canvas.fill(220, 30, 30)
canvas.rect(deliveryManX + 18, deliveryManY, 6, 18) // Red Ribbon
} else {
// Box Handed to Woman
canvas.fill(200, 140, 60)
canvas.rect(houseX + 70, houseY + 15, 22, 18)
canvas.fill(220, 30, 30)
canvas.rect(houseX + 78, houseY + 15, 6, 18)
}
}
// Doorbell Visual Sound Effect
if (deliverySubState == 2 && animationTimer < 30) {
canvas.fill(255, 215, 0)
canvas.text("DING DONG!", houseX + 10, houseY + 65)
}
// Dialogues & Speech Bubbles
if (deliverySubState >= 3) {
// Speech Bubble from Woman
canvas.fill(255, 255, 255)
canvas.stroke(0, 0, 0)
canvas.strokeWeight(2)
canvas.rect(houseX - 190, houseY + 70, 220, 65)
canvas.fill(0, 0, 0)
canvas.text("Thank you for the delivery!", houseX - 180, houseY + 110)
canvas.text("Please visit again!", houseX - 180, houseY + 92)
canvas.fill(180, 0, 60)
canvas.text("Happy Rakshabandhan!", houseX - 180, houseY + 76)
// Continue Button
canvas.fill(0, 180, 80)
canvas.noStroke()
canvas.rect(cwidth / 2 - 90, 20, 180, 45)
canvas.fill(255, 255, 255)
canvas.text("CLICK TO COMPLETE", cwidth / 2 - 75, 38)
}
}
// ============================================================
// OTHER GAME SCREENS
// ============================================================
def drawLetterScreen(canvas: CanvasDraw) {
canvas.background(40, 20, 50)
repeatFor(stars) { s => s.view(canvas) }
canvas.fill(255, 248, 220)
canvas.stroke(212, 175, 55)
canvas.strokeWeight(4)
canvas.rect(cwidth/2 - 200, cheight/2 - 160, 400, 320)
canvas.fill(180, 0, 0)
canvas.text("RAKSHABANDHAN ORDER LETTER", cwidth/2 - 150, cheight/2 + 120)
canvas.fill(50, 50, 50)
canvas.text("Dear Creator,", cwidth/2 - 170, cheight/2 + 80)
canvas.text("Please create a Rakhi and deliver it to:", cwidth/2 - 170, cheight/2 + 50)
canvas.fill(0, 100, 0)
canvas.text("Address: Gokuldham Society,", cwidth/2 - 170, cheight/2 + 10)
canvas.text("Powder Galli, Goregaon East.", cwidth/2 - 170, cheight/2 - 15)
canvas.fill(220, 50, 50)
canvas.rect(cwidth/2 - 90, cheight/2 - 120, 180, 50)
canvas.fill(255, 255, 255)
canvas.text("Accept the Order", cwidth/2 - 65, cheight/2 - 90)
}
def drawAvatarSelection(canvas: CanvasDraw) {
canvas.background(30, 30, 60)
canvas.fill(255, 215, 0)
canvas.text("SELECT YOUR AVATAR", cwidth/2 - 100, cheight - 50)
drawDetailedAvatar(canvas, cwidth/2 - 120, cheight/2, "WOMAN", 1.0)
canvas.fill(255, 255, 255)
canvas.text("WOMAN", cwidth/2 - 150, cheight/2 - 100)
drawDetailedAvatar(canvas, cwidth/2 + 120, cheight/2, "MAN", 1.0)
canvas.fill(255, 255, 255)
canvas.text("MAN", cwidth/2 + 105, cheight/2 - 100)
}
def drawCreateRakhiScreen(canvas: CanvasDraw) {
canvas.background(20, 50, 40)
canvas.fill(255, 255, 255)
canvas.text("DRAW / CREATE THE RAKHI", cwidth/2 - 120, cheight - 50)
val shapes = Array("CIRCLE", "TRIANGLE", "STAR")
for (i <- 0 until 3) {
val bx = 100 + i * 160
canvas.fill(240, 240, 240)
canvas.rect(bx, cheight/2 - 30, 120, 60)
canvas.fill(0, 0, 0)
canvas.text(shapes(i), bx + 25, cheight/2 + 5)
}
if (selectedShape != "") {
drawRakhi(canvas, cwidth/2, 130, selectedShape, threadAttached)
if (!threadAttached) {
canvas.fill(220, 50, 50)
canvas.rect(cwidth/2 - 100, 30, 200, 45)
canvas.fill(255, 255, 255)
canvas.text("Attach Thread (Dhaga)", cwidth/2 - 80, 55)
} else {
canvas.fill(0, 180, 80)
canvas.rect(cwidth/2 - 100, 30, 200, 45)
canvas.fill(255, 255, 255)
canvas.text("Click to Deliver", cwidth/2 - 60, 55)
}
}
}
def drawCompletionScreen(canvas: CanvasDraw) {
canvas.background(20, 60, 30)
repeatFor(stars) { s => s.view(canvas) }
canvas.fill(255, 215, 0)
canvas.text("HAPPY RAKSHABANDHAN!", cwidth/2 - 120, cheight/2 + 80)
canvas.fill(255, 255, 255)
canvas.text("Thank you for completing the mission!", cwidth/2 - 150, cheight/2 + 25)
canvas.fill(200, 220, 255)
canvas.text("Mission Accomplished at Gokuldham Society!", cwidth/2 - 165, cheight/2 - 35)
}
// ============================================================
// ANIMATION STEP UPDATER
// ============================================================
def updateDeliveryAnimation() {
if (screen == 3) {
if (deliverySubState == 0) { // Car Driving
carX += 3.5
if (carX >= cwidth - 360) {
deliverySubState = 1
deliveryManX = carX + 60
deliveryManY = carY + 15
}
} else if (deliverySubState == 1) { // Delivery Man Walking
deliveryManX += 1.5
deliveryManY += 0.4
if (deliveryManX >= cwidth - 150) {
deliverySubState = 2
animationTimer = 0
}
} else if (deliverySubState == 2) { // Ringing Bell & Opening Door
animationTimer += 1
if (animationTimer > 35) {
isDoorOpen = true
deliverySubState = 3
}
} else if (deliverySubState == 3) { // Handing over Box
hasGivenBox = true
}
}
}
// ============================================================
// CLICK HANDLER
// ============================================================
def handleClick(x: Double, y: Double) {
if (screen == 0) {
if (x >= cwidth/2 - 90 && x <= cwidth/2 + 90 && y >= cheight/2 - 120 && y <= cheight/2 - 70) {
screen = 1
}
} else if (screen == 1) {
if (x >= cwidth/2 - 170 && x <= cwidth/2 - 70) {
selectedAvatar = "WOMAN"
screen = 2
} else if (x >= cwidth/2 + 70 && x <= cwidth/2 + 170) {
selectedAvatar = "MAN"
screen = 2
}
} else if (screen == 2) {
if (y >= cheight/2 - 30 && y <= cheight/2 + 30) {
if (x >= 100 && x <= 220) selectedShape = "CIRCLE"
if (x >= 260 && x <= 380) selectedShape = "TRIANGLE"
if (x >= 420 && x <= 540) selectedShape = "STAR"
}
if (selectedShape != "" && x >= cwidth/2 - 100 && x <= cwidth/2 + 100 && y >= 30 && y <= 75) {
if (!threadAttached) {
threadAttached = true
} else {
screen = 3 // Start Delivery Animation Scene
}
}
} else if (screen == 3 && deliverySubState >= 3) {
if (x >= cwidth / 2 - 90 && x <= cwidth / 2 + 90 && y >= 20 && y <= 65) {
screen = 4 // Show Final Completion Screen
}
}
}
onMouseClick { (x, y) => handleClick(x, y) }
// ============================================================
// MAIN LOOP
// ============================================================
animateWithCanvasDraw { canvas =>
repeatFor(stars) { s => s.step() }
updateDeliveryAnimation()
if (screen == 0) drawLetterScreen(canvas)
else if (screen == 1) drawAvatarSelection(canvas)
else if (screen == 2) drawCreateRakhiScreen(canvas)
else if (screen == 3) drawDeliveryAnimationScene(canvas)
else if (screen == 4) drawCompletionScreen(canvas)
}