Code Sketch


BHA,,VEsh 02 art
By: Mhalsakant School
Category: Art
// --- OPERATION SINDOOR WITH TANKS, MULTIPLE MISSILES & WAVING FLAG ---
cleari()
originBottomLeft()

val gravity = Vector2D(0, -0.08)
var waveAngle = 0.0
var chakraRotation = 0.0

// ? ?????????? ????? (Variables for 2 Missiles)
var missile1Y = 0.0
var missile2Y = -120.0 // ????? ?????? ???? ????
val missile1X = (cwidth / 2.0) - 200.0
val missile2X = (cwidth / 2.0) - 150.0
val missileSpeed = 4.0

// ?. ?????? ?????? ?????
val tricolorPalette = Array(
    cm.rgb(255, 153, 51),  // ?????
    cm.rgb(255, 255, 255), // ??????
    cm.rgb(18, 136, 7)     // ?????
)

class Particle(x0: Double, y0: Double, col: Color, seed: Boolean) {
    var location = Vector2D(x0, y0)
    private var velocity =
        if (seed) Vector2D(0, random(5, 11))
        else randomExplosionVector
    private var acceleration = Vector2D(0, 0)
    var lifespan = 255.0
    private var exploded = false

    def randomExplosionVector: Vector2D = {
        val rv1 = Vector2D(randomNormalDouble, randomNormalDouble)
        val r1 = randomDouble(2, 4)
        rv1 * r1
    }

    def applyForce(force: Vector2D) {
        acceleration += force
    }

    def shouldExplode: Boolean = !exploded && lifespan <= 0

    def checkExplode() {
        if (seed && velocity.y < 0) {
            lifespan = 0
        }
    }

    def isDead: Boolean = {
        if (seed) exploded else lifespan <= 0
    }

    def explode() {
        exploded = true
    }

    def step() {
        velocity += acceleration
        location += velocity
        if (!seed) {
            lifespan -= 5
            velocity *= 0.95
        }
        acceleration *= 0
        checkExplode()
    }

    def view(canvas: CanvasDraw) {
        canvas.stroke(col)
        if (seed) {
            canvas.strokeWeight(4)
        } else {
            canvas.strokeWeight(2)
        }
        canvas.point(location.x, location.y)
    }
}

class Firework() {
    private val fireworkColor = tricolorPalette(random(tricolorPalette.length))
    private val firework = new Particle(random(cwidth), 0, fireworkColor, true)
    private val particles = ArrayBuffer.empty[Particle]

    def done: Boolean = {
        firework.isDead && particles.isEmpty
    }

    def step() {
        particles.filterInPlace(p => !p.isDead)

        if (!firework.isDead) {
            firework.applyForce(gravity)
            firework.step()

            if (firework.shouldExplode) {
                repeat(80) {
                    particles.append(
                        new Particle(firework.location.x, firework.location.y, fireworkColor, false)
                    )
                }
                firework.explode()
            }
        }

        repeatFor(particles) { p =>
            p.applyForce(gravity)
            p.step()
        }
    }

    def view(canvas: CanvasDraw) {
        firework.view(canvas)
        repeatFor(particles) { p =>
            p.view(canvas)
        }
    }
}

val fireworks = ArrayBuffer.empty[Firework]

def updateState() {
    fireworks.filterInPlace(f => !f.done)
    if (randomDouble(1) < 0.08) {
        fireworks.append(new Firework())
    }
    repeatFor(fireworks) { f =>
        f.step()
    }
    waveAngle += 0.08
    chakraRotation += 0.05

    // ?????????? ??????
    missile1Y += missileSpeed
    if (missile1Y > cheight + 60) missile1Y = -50.0

    missile2Y += missileSpeed
    if (missile2Y > cheight + 60) missile2Y = -50.0
}

// ?. ? ?????? ????????? ??????
def drawSingleMissile(canvas: CanvasDraw, mx: Double, my: Double) {
    if (my > -40) {
        // ??? (Smoke)
        canvas.fill(180, 180, 180, 140)
        canvas.noStroke()
        canvas.ellipse(mx, my - 30, random(15, 22), random(15, 22))
        canvas.ellipse(mx, my - 50, random(20, 30), random(20, 30))

        // ?? (Thruster Flame)
        canvas.fill(255, 69, 0)
        canvas.ellipse(mx, my - 12, 10, 22)
        canvas.fill(255, 215, 0)
        canvas.ellipse(mx, my - 8, 6, 12)

        // ???? (Missile Body)
        canvas.fill(220, 220, 220)
        canvas.stroke(100, 100, 100)
        canvas.strokeWeight(1)
        canvas.rect(mx - 6, my, 12, 40)

        // ??? (Red Nose)
        canvas.fill(220, 20, 60)
        canvas.line(mx - 6, my + 40, mx, my + 55)
        canvas.line(mx + 6, my + 40, mx, my + 55)

        // ??? (Wings)
        canvas.fill(120, 120, 120)
        canvas.rect(mx - 12, my, 6, 14)
        canvas.rect(mx + 6, my, 6, 14)
    }
}

// ?. ?? ?????? ??? (ARMY BATTLE TANK)
def drawArmyTank(canvas: CanvasDraw, tx: Double, ty: Double) {
    // ?. ????? ?????/???? (Tracks)
    canvas.fill(40, 40, 40)
    canvas.stroke(20, 20, 20)
    canvas.strokeWeight(1)
    canvas.rect(tx - 40, ty, 80, 18)

    // ??????? ????/???????
    canvas.fill(80, 80, 80)
    for (i <- -3 to 3) {
        canvas.ellipse(tx + (i * 11), ty + 9, 8, 8)
    }

    // ?. ????? ????? ???? (Armor Body - Army Green)
    canvas.fill(55, 85, 45)
    canvas.rect(tx - 32, ty + 18, 64, 18)

    // ?. ???? ???? (Turret)
    canvas.fill(40, 70, 35)
    canvas.ellipse(tx, ty + 36, 36, 20)

    // ?. ??? (Cannon Barrel)
    canvas.stroke(30, 55, 25)
    canvas.strokeWeight(6)
    canvas.line(tx - 10, ty + 38, tx - 65, ty + 52) // ?????? ?????? ??????? ???
}

// ?. ??????? ???? ??? ???? ????
def drawWavingTricolorFlag(canvas: CanvasDraw) {
    val fw = 160.0
    val fh = 28.0
    val fx = (cwidth - fw) / 2.0 + 110.0
    val fy = cheight / 2.0 - 10.0

    // ?????????
    canvas.stroke(200, 200, 200)
    canvas.strokeWeight(5)
    canvas.line(fx, fy + fh * 3 + 15, fx, fy - 160)

    val stepSize = 4.0
    var x = 0.0
    while (x < fw) {
        val yOffset = math.sin(waveAngle + (x * 0.03)) * 8.0
        
        canvas.stroke(255, 153, 51)
        canvas.strokeWeight(stepSize + 1)
        canvas.line(fx + x, fy + fh * 2 + yOffset, fx + x, fy + fh * 3 + yOffset)

        canvas.stroke(255, 255, 255)
        canvas.line(fx + x, fy + fh + yOffset, fx + x, fy + fh * 2 + yOffset)

        canvas.stroke(18, 136, 7)
        canvas.line(fx + x, fy + yOffset, fx + x, fy + fh + yOffset)

        x += stepSize
    }

    val chakraX = fx + fw / 2.0
    val chakraY = fy + fh + (fh / 2.0) + (math.sin(waveAngle + ((fw / 2.0) * 0.03)) * 8.0)
    val radius = 11.0

    canvas.stroke(0, 0, 128)
    canvas.strokeWeight(2)
    canvas.noFill()
    canvas.ellipse(chakraX, chakraY, radius * 2, radius * 2)

    canvas.strokeWeight(1)
    for (i <- 0 until 24) {
        val angle = chakraRotation + (i * (2 * math.Pi / 24))
        val xEnd = chakraX + math.cos(angle) * radius
        val yEnd = chakraY + math.sin(angle) * radius
        canvas.line(chakraX, chakraY, xEnd, yEnd)
    }
}

// ?. ? "OPERATION SINDOOR" ???? ????? ?????
def drawBigOperationSindoorTitle(canvas: CanvasDraw) {
    val startX = 25.0
    val startY = cheight - 60.0

    // ?. OPERATION - ?????? ??? (Grey Color)
    canvas.fill(160, 160, 160)
    canvas.text("OPERATION", startX, startY)

    // ?. SINDOOR - ???/?????? ??? (Red Color)
    canvas.fill(220, 20, 20)
    canvas.text("SINDOOR", startX, startY - 35.0)
}

def viewState(canvas: CanvasDraw) {
    // ??????? ???????????
    canvas.fill(10, 10, 25, 45)
    canvas.noStroke()
    canvas.rect(0, 0, cwidth, cheight)

    // ?. ?????? ?????
    repeatFor(fireworks) { f =>
        f.view(canvas)
    }

    // ?. ???????? ?????? (? Missiles)
    drawSingleMissile(canvas, missile1X, missile1Y)
    drawSingleMissile(canvas, missile2X, missile2Y)

    // ?. ?????? ??? (Army Tank)
    drawArmyTank(canvas, (cwidth / 2.0) + 120.0, 30.0)

    // ?. ???? OPERATION SINDOOR ?????
    drawBigOperationSindoorTitle(canvas)

    // ?. ??????? ?????? ????
    drawWavingTricolorFlag(canvas)
}

animateWithCanvasDraw { canvas =>
    updateState()
    viewState(canvas)
}