Code Sketch
HARDEST GAME02
Category: Art
// --- OPERATION SINDOOR: ENHANCED MISSILE SYSTEM (FIXED) ---
cleari()
originBottomLeft()
val gravity = Vector2D(0, -0.08)
var waveAngle = 0.0
var chakraRotation = 0.0
var missileX = cwidth / 2.0 - 180.0
var missileY = 150.0
var missileAngle = math.Pi / 2.0
var selectedMissileType = 1
// --- 1. ADVANCED STRATEGIC MISSILE SYSTEM ---
class StrategicMissile(var x: Double, var y: Double, val vx: Double, val vy: Double, var angle: Double, val mType: Int) {
var active = true
var flightTime = 0.0
var trail = ArrayBuffer.empty[Vector2D]
def step() {
flightTime += 1.0
if (mType == 2) {
angle += 0.006
} else if (mType == 3) {
angle += math.sin(x * 0.06) * 0.03
}
val speed = math.sqrt(vx*vx + vy*vy) * (if (mType == 2) 1.15 else 1.0)
x += math.cos(angle) * speed
y += math.sin(angle) * speed
trail.append(Vector2D(x, y))
if (trail.length > 22) trail.remove(0)
if (x < -100 || x > cwidth + 100 || y < -100 || y > cheight + 100) active = false
}
def view(canvas: CanvasDraw) {
canvas.noStroke()
for (i <- 0 until trail.length) {
val alpha = ((i.toDouble / trail.length) * 150).toInt
if (mType == 3) {
canvas.fill(0, 255, 255, alpha)
} else if (mType == 2) {
canvas.fill(255, 140, 0, alpha)
} else {
canvas.fill(255, 80, 0, alpha)
}
canvas.ellipse(trail(i).x, trail(i).y, 5 + (i * 0.2), 5 + (i * 0.2))
}
canvas.pushMatrix()
canvas.translate(x, y)
canvas.rotate(angle)
if (mType == 1) {
canvas.fill(210, 210, 220)
canvas.stroke(40, 40, 50)
canvas.strokeWeight(1)
canvas.rect(-22, -7, 44, 14)
canvas.fill(180, 20, 20)
canvas.noStroke()
canvas.ellipse(22, 0, 14, 14)
canvas.fill(50, 50, 50)
canvas.rect(-28, -10, 8, 20)
} else if (mType == 2) {
canvas.fill(45, 50, 60)
canvas.stroke(15, 15, 20)
canvas.rect(-28, -11, 56, 22)
canvas.fill(240, 160, 20)
canvas.ellipse(28, 0, 18, 18)
canvas.fill(90, 90, 90)
canvas.rect(-34, -15, 10, 30)
canvas.stroke(15, 15, 20)
canvas.strokeWeight(2)
canvas.line(-20, -11, -30, -22)
canvas.line(-30, -22, -10, -11)
canvas.line(-20, 11, -30, 22)
canvas.line(-30, 22, -10, 11)
} else {
canvas.fill(20, 110, 170)
canvas.stroke(10, 40, 80)
canvas.rect(-20, -6, 40, 12)
canvas.fill(0, 255, 255)
canvas.noStroke()
canvas.ellipse(20, 0, 12, 12)
canvas.fill(255, 255, 0)
canvas.rect(-14, -3, 26, 6)
canvas.fill(255, 255, 255, 200)
canvas.ellipse(0, 0, 8, 8)
}
canvas.fill(255, 200, 0, 240)
canvas.noStroke()
canvas.ellipse(-28, 0, 16, 10)
canvas.fill(255, 69, 0, 190)
canvas.ellipse(-35, 0, 22, 6)
canvas.popMatrix()
canvas.stroke(0, 255, 100, 120)
canvas.strokeWeight(1)
canvas.noFill()
canvas.rect(x - 15, y - 15, 30, 30)
}
}
val strategicMissiles = ArrayBuffer.empty[StrategicMissile]
// --- 2. HEAVY REALISTIC TANK & SHELLS ---
var tankX = cwidth / 2.0 + 120.0
val tankY = 30.0
var cannonAngle = math.Pi / 2.0
var muzzleFlashTimer = 0
class TankShell(var x: Double, var y: Double, val vx: Double, val vy: Double) {
var active = true
def step() {
x += vx
y += vy
if (x < -50 || x > cwidth + 50 || y < -50 || y > cheight + 50) active = false
}
def view(canvas: CanvasDraw) {
canvas.fill(255, 140, 0)
canvas.noStroke()
canvas.ellipse(x, y, 10, 10)
canvas.fill(255, 69, 0, 180)
canvas.ellipse(x - vx * 2, y - vy * 2, 7, 7)
}
}
val tankShells = ArrayBuffer.empty[TankShell]
// --- 3. ENEMY THREAT MISSILES ---
class EnemyMissile(var x: Double, var y: Double, var vy: Double) {
var active = true
var exploded = false
var explosionTimer = 0
def step() {
if (!exploded) {
y += vy
if (y < 0) active = false
} else {
explosionTimer += 1
if (explosionTimer > 35) active = false
}
}
def view(canvas: CanvasDraw) {
if (!exploded) {
canvas.pushMatrix()
canvas.translate(x, y)
canvas.rotate(-math.Pi / 2)
canvas.fill(170, 30, 30)
canvas.stroke(70, 10, 10)
canvas.strokeWeight(1)
canvas.rect(-18, -6, 36, 12)
canvas.fill(50, 50, 50)
canvas.noStroke()
canvas.ellipse(18, 0, 10, 10)
canvas.popMatrix()
canvas.stroke(255, 50, 50, 100)
canvas.strokeWeight(1)
canvas.noFill()
canvas.ellipse(x, y, 40, 40)
} else {
canvas.noStroke()
canvas.fill(255, 90, 0, 190)
canvas.ellipse(x, y, 70 + explosionTimer * 2.5, 70 + explosionTimer * 2.5)
canvas.fill(255, 255, 0, 230)
canvas.ellipse(x, y, 35, 35)
}
}
}
val enemyMissiles = ArrayBuffer.empty[EnemyMissile]
var enemySpawnTimer = 0
// --- 4. TRICOLOR CELEBRATORY FIREWORKS ---
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(6, 12)) else randomExplosionVector
private var acceleration = Vector2D(0, 0)
var lifespan = 255.0
private var exploded = false
def randomExplosionVector: Vector2D = {
val rv1 = Vector2D(randomNormalDouble, randomNormalDouble)
rv1 * randomDouble(2, 5)
}
def applyForce(force: Vector2D) { acceleration = 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 = velocity + acceleration
location = location + velocity
if (!seed) {
lifespan -= 4
velocity = velocity * 0.94
}
acceleration = Vector2D(0, 0)
checkExplode()
}
def view(canvas: CanvasDraw) {
canvas.stroke(col)
if (seed) canvas.strokeWeight(5) 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(90) {
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
if (mouseX >= 20 && mouseX <= 75 && mouseY >= 90 && mouseY <= 130) tankX -= 3.0
else if (mouseX >= 80 && mouseX <= 135 && mouseY >= 90 && mouseY <= 130) tankX += 3.0
else if (mouseX >= 140 && mouseX <= 195 && mouseY >= 90 && mouseY <= 130) cannonAngle -= 0.05
else if (mouseX >= 200 && mouseX <= 255 && mouseY >= 90 && mouseY <= 130) cannonAngle += 0.05
else if (mouseX >= 260 && mouseX <= 315 && mouseY >= 90 && mouseY <= 130) {
val tbx = tankX; val tby = tankY + 36.0; val bl = 60.0
val tx = tbx + math.cos(cannonAngle) * bl
val ty = tby + math.sin(cannonAngle) * bl
tankShells.append(new TankShell(tx, ty, math.cos(cannonAngle) * 8.0, math.sin(cannonAngle) * 8.0))
muzzleFlashTimer = 8
}
else if (mouseX >= 325 && mouseX <= 375 && mouseY >= 90 && mouseY <= 130) missileAngle -= 0.05
else if (mouseX >= 380 && mouseX <= 430 && mouseY >= 90 && mouseY <= 130) missileAngle += 0.05
else if (mouseX >= 435 && mouseX <= 485 && mouseY >= 90 && mouseY <= 130) selectedMissileType = 1
else if (mouseX >= 490 && mouseX <= 540 && mouseY >= 90 && mouseY <= 130) selectedMissileType = 2
else if (mouseX >= 545 && mouseX <= 595 && mouseY >= 90 && mouseY <= 130) selectedMissileType = 3
else if (mouseX >= 600 && mouseX <= 675 && mouseY >= 90 && mouseY <= 130) {
val mTipX = missileX + math.cos(missileAngle) * 50.0
val mTipY = missileY + math.sin(missileAngle) * 50.0
strategicMissiles.append(new StrategicMissile(mTipX, mTipY, math.cos(missileAngle) * 6.5, math.sin(missileAngle) * 6.5, missileAngle, selectedMissileType))
}
if (tankX < 60.0) tankX = 60.0
if (tankX > cwidth - 60.0) tankX = cwidth - 60.0
if (muzzleFlashTimer > 0) muzzleFlashTimer -= 1
enemySpawnTimer += 1
if (enemySpawnTimer >= 90) {
enemySpawnTimer = 0
val ex = random(120, cwidth - 120)
enemyMissiles.append(new EnemyMissile(ex, cheight + 20.0, -0.8))
}
tankShells.filterInPlace(_.active)
repeatFor(tankShells) { s => s.step() }
strategicMissiles.filterInPlace(_.active)
repeatFor(strategicMissiles) { sm => sm.step() }
enemyMissiles.filterInPlace(_.active)
repeatFor(enemyMissiles) { em => em.step() }
repeatFor(enemyMissiles) { em =>
if (!em.exploded) {
repeatFor(tankShells) { ts =>
if (ts.active && math.abs(ts.x - em.x) < 25 && math.abs(ts.y - em.y) < 25) {
em.exploded = true; ts.active = false
}
}
repeatFor(strategicMissiles) { sm =>
if (sm.active && math.abs(sm.x - em.x) < 38 && math.abs(sm.y - em.y) < 38) {
em.exploded = true; sm.active = false
}
}
}
}
}
def drawLauncherPad(canvas: CanvasDraw, mx: Double, my: Double) {
canvas.fill(50, 55, 65)
canvas.stroke(20, 25, 30)
canvas.strokeWeight(2)
canvas.ellipse(mx, my, 55, 55)
canvas.pushMatrix()
canvas.translate(mx, my)
canvas.rotate(missileAngle)
canvas.fill(70, 80, 75)
canvas.stroke(30, 40, 35)
canvas.strokeWeight(2)
canvas.rect(-14, -16, 60, 32)
if (selectedMissileType == 1) canvas.fill(200, 30, 30)
else if (selectedMissileType == 2) canvas.fill(220, 140, 0)
else canvas.fill(0, 200, 255)
canvas.rect(15, -16, 8, 32)
canvas.popMatrix()
}
def drawRealisticArmyTank(canvas: CanvasDraw, tx: Double, ty: Double) {
canvas.fill(30, 33, 38)
canvas.stroke(10, 10, 12)
canvas.strokeWeight(1)
canvas.rect(tx - 50, ty, 100, 22)
canvas.fill(70, 75, 70)
for (i <- -4 to 4) {
canvas.ellipse(tx + (i * 11), ty + 11, 9, 9)
}
canvas.fill(50, 80, 45)
canvas.rect(tx - 40, ty + 22, 80, 20)
canvas.fill(40, 70, 35)
canvas.ellipse(tx, ty + 44, 44, 24)
val turretBaseX = tx
val turretBaseY = ty + 44.0
val barrelLength = 65.0
canvas.stroke(25, 50, 20)
canvas.strokeWeight(8)
val tipX = turretBaseX + math.cos(cannonAngle) * barrelLength
val tipY = turretBaseY + math.sin(cannonAngle) * barrelLength
canvas.line(turretBaseX, turretBaseY, tipX, tipY)
if (muzzleFlashTimer > 0) {
canvas.noStroke()
canvas.fill(255, 140, 0, 230)
canvas.ellipse(tipX, tipY, 35, 35)
canvas.fill(255, 255, 0, 250)
canvas.ellipse(tipX, tipY, 20, 20)
canvas.fill(255, 255, 255)
canvas.ellipse(tipX, tipY, 10, 10)
}
}
def drawControlButtons(canvas: CanvasDraw) {
canvas.fill(20, 20, 35, 210)
canvas.stroke(180, 180, 200)
canvas.strokeWeight(1)
canvas.rect(15, 85, 665, 50)
canvas.fill(50, 50, 80); canvas.rect(20, 95, 50, 30); canvas.fill(cm.rgb(255, 255, 255)); canvas.text("<- T", 30, 105)
canvas.fill(50, 50, 80); canvas.rect(75, 95, 50, 30); canvas.fill(cm.rgb(255, 255, 255)); canvas.text("T ->", 85, 105)
canvas.fill(70, 40, 40); canvas.rect(130, 95, 50, 30); canvas.fill(cm.rgb(255, 255, 255)); canvas.text("<- C", 140, 105)
canvas.fill(70, 40, 40); canvas.rect(185, 95, 50, 30); canvas.fill(cm.rgb(255, 255, 255)); canvas.text("C ->", 195, 105)
canvas.fill(200, 70, 0); canvas.rect(240, 95, 55, 30); canvas.fill(cm.rgb(255, 255, 255)); canvas.text("FIRE", 252, 105)
canvas.fill(40, 90, 90); canvas.rect(300, 95, 45, 30); canvas.fill(cm.rgb(255, 255, 255)); canvas.text("<- M", 308, 105)
canvas.fill(40, 90, 90); canvas.rect(350, 95, 45, 30); canvas.fill(cm.rgb(255, 255, 255)); canvas.text("M ->", 358, 105)
canvas.fill(if (selectedMissileType == 1) 180 else 80, 30, 120); canvas.rect(400, 95, 45, 30); canvas.fill(cm.rgb(255, 255, 255)); canvas.text("BRM", 408, 105)
canvas.fill(if (selectedMissileType == 2) 180 else 80, 30, 120); canvas.rect(450, 95, 45, 30); canvas.fill(cm.rgb(255, 255, 255)); canvas.text("AGN", 458, 105)
canvas.fill(if (selectedMissileType == 3) 180 else 80, 30, 120); canvas.rect(500, 95, 45, 30); canvas.fill(cm.rgb(255, 255, 255)); canvas.text("SUD", 508, 105)
canvas.fill(140, 0, 180); canvas.rect(555, 95, 75, 30); canvas.fill(cm.rgb(255, 255, 255)); canvas.text("LAUNCH", 568, 105)
}
def drawWavingTricolorFlag(canvas: CanvasDraw) {
val fw = 160.0; val fh = 28.0
val fx = (cwidth - fw) / 2.0 + 130.0
val fy = cheight / 2.0 - 20.0
canvas.stroke(210, 210, 210); canvas.strokeWeight(6)
canvas.line(fx, fy + fh * 3 + 15, fx, fy - 170)
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, 130); 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))
canvas.line(chakraX, chakraY, chakraX + math.cos(angle) * radius, chakraY + math.sin(angle) * radius)
}
}
def viewState(canvas: CanvasDraw) {
canvas.fill(10, 10, 25, 45)
canvas.noStroke()
canvas.rect(0, 0, cwidth, cheight)
repeatFor(fireworks) { f => f.view(canvas) }
drawLauncherPad(canvas, missileX, missileY)
drawRealisticArmyTank(canvas, tankX, tankY)
drawControlButtons(canvas)
repeatFor(tankShells) { s => s.view(canvas) }
repeatFor(strategicMissiles) { sm => sm.view(canvas) }
repeatFor(enemyMissiles) { em => em.view(canvas) }
drawWavingTricolorFlag(canvas)
}
animateWithCanvasDraw { canvas =>
updateState()
viewState(canvas)
}