Code Sketch


Bixuu02
By: Mhalsakant School
Category: Programming
// ============================================================
// BIXUU CAR WASH & PAINT MISSION GAME
// SCALA SCRIPT FOR KOJO / SCALA CANVAS
// ============================================================

cleari()
originBottomLeft()

// ============================================================
// GAME STATES & VARIABLES
// 0 = Intro Screen (Prize & Thanks)
// 1 = Mission Letter Screen
// 2 = Car Cleaning & Painting Scene
// 3 = Delivery Scene (Birds House)
// 4 = Final Screen (Bixuu Speech & Second Round)
// ============================================================
var screen = 0
var selectedTool = "NONE" // "WATER", "BRUSH"
var carCleaned = false
var carColorR = 180
var carColorG = 180
var carColorB = 180
var carColorName = "DIRTY"

// Delivery Animation Variables
var carX = -120.0
var carY = 100.0
var deliveryManX = 0.0
var deliveryManY = 0.0
var deliverySubState = 0 
var isDoorOpen = false
var animTimer = 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 CUSTOM CAR (DIRTY OR PAINTED)
// ============================================================
def drawCar(canvas: CanvasDraw, x: Double, y: Double, r: Int, g: Int, b: Int, isDirty: Boolean) {
    canvas.noStroke()
    
    // Shadow
    canvas.fill(40, 40, 40, 100)
    canvas.ellipse(x + 90, y - 5, 180, 20)

    // Car Main Body
    canvas.fill(r, g, b)
    canvas.rect(x, y + 10, 170, 50)
    canvas.rect(x + 35, y + 60, 95, 40)

    // Windows
    canvas.fill(180, 220, 255)
    canvas.rect(x + 40, y + 63, 40, 32)
    canvas.rect(x + 85, y + 63, 40, 32)

    // Lights
    canvas.fill(255, 230, 0)
    canvas.rect(x + 165, y + 25, 8, 15)
    canvas.fill(200, 0, 0)
    canvas.rect(x - 3, y + 25, 6, 15)

    // Wheels
    val wheelPositions = Array(x + 40, x + 130)
    for (wx <- wheelPositions) {
        canvas.fill(20, 20, 20)
        canvas.ellipse(wx, y + 8, 40, 40)
        canvas.fill(180, 180, 180)
        canvas.ellipse(wx, y + 8, 22, 22)
    }

    // Dust Layer on Car if Dirty
    if (isDirty) {
        canvas.fill(140, 100, 50, 210) // Mud / Dust Color
        canvas.rect(x - 2, y + 8, 174, 95)
        canvas.fill(110, 80, 40)
        canvas.ellipse(x + 40, y + 40, 50, 30)
        canvas.ellipse(x + 120, y + 30, 60, 40)
        canvas.ellipse(x + 80, y + 70, 45, 25)
    }
}

// ============================================================
// SCREENS
// ============================================================

// --- SCREEN 0: INTRO SCREEN ---
def drawIntroScreen(canvas: CanvasDraw) {
    canvas.background(25, 15, 45)
    repeatFor(stars) { s => s.view(canvas) }

    canvas.fill(255, 215, 0)
    canvas.text("THANK YOU FOR SEE BIXUU MISSION!", cwidth/2 - 170, cheight - 50)

    canvas.fill(255, 255, 255)
    canvas.text("Bixuu is created by a game.", cwidth/2 - 120, cheight - 90)
    canvas.text("Join 100 people on this game!", cwidth/2 - 135, cheight - 120)

    // Prize Card
    canvas.fill(40, 30, 70)
    canvas.stroke(255, 215, 0)
    canvas.strokeWeight(3)
    canvas.rect(cwidth/2 - 170, cheight/2 - 70, 340, 140)

    canvas.noStroke()
    canvas.fill(255, 215, 0)
    canvas.text("PRIZE POOL ANNOUNCEMENT", cwidth/2 - 120, cheight/2 + 45)
    canvas.fill(255, 255, 255)
    canvas.text("1st Prize Winner : 1 Lakh", cwidth/2 - 120, cheight/2 + 15)
    canvas.text("2nd Prize Winner : 50,000", cwidth/2 - 120, cheight/2 - 10)
    canvas.text("3rd Prize Winner : 20,000", cwidth/2 - 120, cheight/2 - 35)

    // Click Mission Button
    canvas.fill(220, 50, 50)
    canvas.rect(cwidth/2 - 100, 40, 200, 50)
    canvas.fill(255, 255, 255)
    canvas.text("PLEASE CLICK THE MISSION", cwidth/2 - 88, 70)
}

// --- SCREEN 1: ORDER LETTER ---
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 - 190, cheight/2 - 140, 380, 280)

    canvas.fill(180, 0, 0)
    canvas.text("BIXUU MISSION ORDER LETTER", cwidth/2 - 135, cheight/2 + 100)

    canvas.fill(50, 50, 50)
    canvas.text("Mission Objective:", cwidth/2 - 160, cheight/2 + 60)
    canvas.text("1. Clean the dust from the dirty car.", cwidth/2 - 160, cheight/2 + 30)
    canvas.text("2. Paint the car with your favorite color.", cwidth/2 - 160, cheight/2)
    canvas.text("3. Drive & deliver it safely to Birds House.", cwidth/2 - 160, cheight/2 - 30)

    canvas.fill(220, 50, 50)
    canvas.rect(cwidth/2 - 90, cheight/2 - 110, 180, 45)
    canvas.fill(255, 255, 255)
    canvas.text("START MISSION", cwidth/2 - 55, cheight/2 - 82)
}

// --- SCREEN 2: CAR CLEANING & PAINTING ---
def drawCarPaintScreen(canvas: CanvasDraw) {
    canvas.background(30, 40, 50)

    canvas.fill(255, 255, 255)
    canvas.text("BIXUU GARAGE: CLEAN & PAINT THE CAR", cwidth/2 - 160, cheight - 35)

    // Tools Header
    canvas.fill(200, 200, 200)
    canvas.rect(30, cheight - 110, cwidth - 60, 55)

    // Water Tool Button
    if (selectedTool == "WATER") canvas.fill(0, 180, 255) else canvas.fill(100, 100, 100)
    canvas.rect(40, cheight - 102, 110, 40)
    canvas.fill(255, 255, 255)
    canvas.text("WATER (Clean)", 48, cheight - 77)

    // Colors: Blue, Red, Green, Yellow, Orange
    val colorNames = Array("BLUE", "RED", "GREEN", "YELLOW", "ORANGE")
    val colorsR = Array(30, 220, 40, 240, 255)
    val colorsG = Array(100, 30, 180, 220, 130)
    val colorsB = Array(220, 30, 50, 30, 0)

    for (i <- 0 until 5) {
        val bx = 170 + i * 85
        canvas.fill(colorsR(i), colorsG(i), colorsB(i))
        canvas.rect(bx, cheight - 102, 75, 40)
        canvas.fill(255, 255, 255)
        canvas.text(colorNames(i), bx + 12, cheight - 77)
    }

    // Draw Main Car
    drawCar(canvas, cwidth/2 - 85, cheight/2 - 40, carColorR, carColorG, carColorB, !carCleaned)

    // Instruction Banner
    canvas.fill(255, 255, 255)
    if (!carCleaned) {
        canvas.text("Step 1: Click 'WATER' button to wash off dust!", cwidth/2 - 150, 120)
    } else {
        canvas.text("Step 2: Click any COLOR to paint the car!", cwidth/2 - 140, 120)
    }

    // Finish / Deliver Button
    if (carCleaned && carColorName != "DIRTY") {
        canvas.fill(0, 180, 80)
        canvas.rect(cwidth/2 - 130, 35, 260, 50)
        canvas.fill(255, 255, 255)
        canvas.text("Thank you for coloring of car!", cwidth/2 - 110, 65)
    }
}

// --- SCREEN 3: DELIVERY AT BIRDS HOUSE ---
def drawDeliveryScene(canvas: CanvasDraw) {
    canvas.background(135, 206, 235)

    // Ground & Road
    canvas.noStroke()
    canvas.fill(40, 160, 60)
    canvas.rect(0, 0, cwidth, 160)
    canvas.fill(70, 70, 75)
    canvas.rect(0, 80, cwidth, 70)
    canvas.fill(255, 255, 255)
    for (i <- 0 until 10) canvas.rect(i * 70, 110, 40, 8)

    // Birds House
    val houseX = cwidth - 190.0
    val houseY = 140.0
    canvas.fill(255, 235, 205)
    canvas.rect(houseX, houseY, 160, 130)
    canvas.fill(160, 82, 45)
    canvas.rect(houseX - 10, houseY + 130, 180, 45)

    // Door Frame
    canvas.fill(100, 50, 20)
    canvas.rect(houseX + 60, houseY, 50, 80)

    // Birds House Name Tag
    canvas.fill(30, 120, 60)
    canvas.rect(houseX + 20, houseY + 98, 120, 25)
    canvas.fill(255, 255, 255)
    canvas.text("BIRDS HOUSE", houseX + 30, houseY + 105)

    // Draw Delivered Car
    drawCar(canvas, carX, carY, carColorR, carColorG, carColorB, false)

    // Owner (From Birds House)
    if (isDoorOpen) {
        canvas.fill(255, 220, 180)
        canvas.ellipse(houseX + 85, houseY + 60, 30, 30) // Head
        canvas.fill(200, 50, 50)
        canvas.rect(houseX + 72, houseY + 15, 26, 35) // Shirt
    }

    // Delivery Driver
    if (deliverySubState >= 1) {
        canvas.fill(255, 220, 180)
        canvas.ellipse(deliveryManX, deliveryManY + 30, 30, 30)
        canvas.fill(40, 90, 180)
        canvas.rect(deliveryManX - 13, deliveryManY - 10, 26, 35)
    }

    // Speech Dialogues
    if (deliverySubState >= 2) {
        canvas.fill(255, 255, 255)
        canvas.stroke(0, 0, 0)
        canvas.strokeWeight(2)
        canvas.rect(houseX - 220, houseY + 60, 240, 75)
        canvas.fill(0, 0, 0)
        canvas.text("Owner: Thank you for coloring my car", houseX - 210, houseY + 115)
        canvas.text("and taking care of my car!", houseX - 210, houseY + 100)
        canvas.fill(0, 100, 200)
        canvas.text("Driver: Thank you! Please visit my", houseX - 210, houseY + 80)
        canvas.text("garage again!", houseX - 210, houseY + 65)

        // Continue Button
        canvas.fill(0, 180, 80)
        canvas.noStroke()
        canvas.rect(cwidth / 2 - 80, 20, 160, 45)
        canvas.fill(255, 255, 255)
        canvas.text("CONTINUE", cwidth / 2 - 40, 38)
    }
}

// --- SCREEN 4: BIXUU SPEECH & END ---
def drawFinalScreen(canvas: CanvasDraw) {
    canvas.background(20, 30, 50)
    repeatFor(stars) { s => s.view(canvas) }

    canvas.fill(255, 215, 0)
    canvas.text("THIS IS BIXUU SPEECH", cwidth/2 - 100, cheight - 60)

    canvas.fill(255, 255, 255)
    canvas.text("Second round coming soon, please wait!", cwidth/2 - 160, cheight/2 + 30)

    canvas.fill(0, 220, 120)
    canvas.text("THANK YOU FOR COMPLETING THE MISSION!", cwidth/2 - 180, cheight/2 - 30)
}

// ============================================================
// LOGIC UPDATER & CLICK HANDLERS
// ============================================================
def updateDelivery() {
    if (screen == 3) {
        if (deliverySubState == 0) { // Driving
            carX += 3.5
            if (carX >= cwidth - 360) {
                deliverySubState = 1
                deliveryManX = carX + 60
                deliveryManY = carY + 15
            }
        } else if (deliverySubState == 1) { // Walking
            deliveryManX += 1.5
            deliveryManY += 0.4
            if (deliveryManX >= cwidth - 150) {
                isDoorOpen = true
                deliverySubState = 2
            }
        }
    }
}

def handleClick(x: Double, y: Double) {
    if (screen == 0) { // Intro -> Letter
        if (x >= cwidth/2 - 100 && x <= cwidth/2 + 100 && y >= 40 && y <= 90) {
            screen = 1
        }
    } else if (screen == 1) { // Letter -> Garage
        if (x >= cwidth/2 - 90 && x <= cwidth/2 + 90 && y >= cheight/2 - 110 && y <= cheight/2 - 65) {
            screen = 2
        }
    } else if (screen == 2) { // Cleaning & Painting Logic
        // Water Tool
        if (x >= 40 && x <= 150 && y >= cheight - 102 && y <= cheight - 62) {
            selectedTool = "WATER"
            carCleaned = true
        }

        // Colors selection (If car is cleaned)
        if (carCleaned && y >= cheight - 102 && y <= cheight - 62) {
            val colorsR = Array(30, 220, 40, 240, 255)
            val colorsG = Array(100, 30, 180, 220, 130)
            val colorsB = Array(220, 30, 50, 30, 0)
            val colorNames = Array("BLUE", "RED", "GREEN", "YELLOW", "ORANGE")

            for (i <- 0 until 5) {
                val bx = 170 + i * 85
                if (x >= bx && x <= bx + 75) {
                    carColorR = colorsR(i)
                    carColorG = colorsG(i)
                    carColorB = colorsB(i)
                    carColorName = colorNames(i)
                }
            }
        }

        // Deliver Button Click
        if (carCleaned && carColorName != "DIRTY" && x >= cwidth/2 - 130 && x <= cwidth/2 + 130 && y >= 35 && y <= 85) {
            screen = 3 // Go to Delivery
        }
    } else if (screen == 3 && deliverySubState == 2) {
        if (x >= cwidth / 2 - 80 && x <= cwidth / 2 + 80 && y >= 20 && y <= 65) {
            screen = 4 // Go to Final Bixuu Speech Screen
        }
    }
}

onMouseClick { (x, y) => handleClick(x, y) }

// ============================================================
// MAIN LOOP
// ============================================================
animateWithCanvasDraw { canvas =>
    repeatFor(stars) { s => s.step() }
    updateDelivery()

    if (screen == 0) drawIntroScreen(canvas)
    else if (screen == 1) drawLetterScreen(canvas)
    else if (screen == 2) drawCarPaintScreen(canvas)
    else if (screen == 3) drawDeliveryScene(canvas)
    else if (screen == 4) drawFinalScreen(canvas)
}