Code Sketch
bhavesh or yadnesh using gemeni
Category: Programming
// --- ISRO MISSION: CURVED RIGHT LAUNCH & SLOW START WITH NEW MESSAGE ---
cleari()
originBottomLeft()
val gravity = Vector2D(0, -0.08)
var waveAngle = 0.0
var chakraRotation = 0.0
val planetList = Array("Mercury", "Venus", "Earth", "Moon", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune")
var selectedPlanet = "Mars"
var isZoomed = false
var isTimerRunning = false
var countdownTimer = 10.0
var isLaunched = false
var isLanded = false
var doorOpenProgress = 0.0
var astronautStep = 0.0
var targetX = (cwidth / 2.0) + 80.0
var targetY = (cheight / 2.0) + 30.0
// ??????? ?????????? ????? (??????)
var rocketX = 80.0
var rocketY = 60.0
var launchProgress = 0.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) }
}
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 (isTimerRunning && countdownTimer > 0) {
countdownTimer -= 0.03
if (countdownTimer <= 0) {
countdownTimer = 0
isTimerRunning = false
isLaunched = true
launchProgress = 0.0
}
}
// ? ???? ?????? ??? ??? ??????? ?????? ????? (Bezier / Curved Path)
if (isLaunched && !isLanded) {
launchProgress += 0.006 // ??? ?????
if (launchProgress >= 1.0) {
launchProgress = 1.0
isLanded = true
}
// ?????? ????? ?????????? (???? ????????? ????? ?????? ???)
val startX = 80.0
val startY = 60.0
val controlX = cwidth / 2.0 + 150.0 // ?????? ?????? ??????? ??????? ?????
val controlY = cheight / 2.0 - 50.0
val u = launchProgress
val tt = u * u
val uu = (1.0 - u) * (1.0 - u)
rocketX = uu * startX + 2 * (1.0 - u) * u * controlX + tt * targetX
rocketY = uu * startY + 2 * (1.0 - u) * u * controlY + tt * targetY
}
if (isLanded) {
if (doorOpenProgress < 1.0) {
doorOpenProgress += 0.02
} else if (astronautStep < 1.0) {
astronautStep += 0.02
}
}
}
onMouseClick { (x, y) =>
if (x >= 20 && x <= 110 && y >= 15 && y <= 50) {
if (!isTimerRunning && !isLaunched) {
isTimerRunning = true
countdownTimer = 10.0
}
}
else if (x <= 130 && y >= cheight - 320 && y <= cheight - 50) {
val index = ((cheight - 50 - y) / 28).toInt
if (index >= 0 && index < planetList.length) {
selectedPlanet = planetList(index)
isZoomed = true
targetX = cwidth / 2.0 + 80.0
targetY = cheight / 2.0 + 30.0
isLanded = false
isLaunched = false
doorOpenProgress = 0.0
astronautStep = 0.0
rocketX = 80.0
rocketY = 60.0
launchProgress = 0.0
}
}
else {
if (isZoomed && !isLaunched) {
targetX = x.toDouble
targetY = y.toDouble
} else if (!isZoomed && x > 140) {
isZoomed = true
}
}
}
def drawPlanetList(canvas: CanvasDraw) {
canvas.fill(15, 20, 35, 200)
canvas.stroke(100, 100, 150)
canvas.strokeWeight(1)
canvas.rect(10, cheight - 330, 120, 275)
canvas.fill(255, 153, 51)
canvas.text("ALL PLANETS", 20, cheight - 70)
var yPos = cheight - 95.0
repeatFor(planetList) { pName =>
if (pName == selectedPlanet) {
canvas.fill(18, 136, 7)
canvas.rect(12, yPos - 12, 116, 22)
canvas.fill(255, 255, 255)
} else {
canvas.fill(200, 200, 200)
}
canvas.text(s"? $pName", 22, yPos)
yPos -= 28.0
}
}
def drawSolarSystem(canvas: CanvasDraw) {
val cx = cwidth / 2.0 + 80
val cy = cheight / 2.0 + 20
canvas.fill(255, 140, 0)
canvas.stroke(255, 215, 0)
canvas.strokeWeight(3)
canvas.ellipse(cx - 160, cy, 65, 65)
canvas.noFill()
canvas.stroke(80, 80, 110)
canvas.strokeWeight(1)
val rList = Array(70, 100, 130, 150, 180, 220, 260, 290, 320)
repeatFor(rList) { r =>
canvas.ellipse(cx - 160, cy, r * 2, r * 1.2)
}
canvas.fill(255, 255, 255)
canvas.text("CLICK ANY PLANET TO ZOOM & AIM!", cx - 100, cheight - 40)
}
def drawZoomedPlanet(canvas: CanvasDraw) {
val px = cwidth / 2.0 + 80
val py = cheight / 2.0 + 20
selectedPlanet match {
case "Jupiter" =>
canvas.fill(210, 150, 100)
canvas.ellipse(px, py, 220, 220)
canvas.fill(170, 100, 60)
canvas.rect(px - 108, py - 30, 216, 22)
canvas.rect(px - 105, py + 20, 210, 18)
canvas.fill(180, 50, 40)
canvas.ellipse(px + 40, py - 40, 42, 28)
case "Saturn" =>
canvas.fill(220, 190, 140)
canvas.ellipse(px, py, 180, 180)
canvas.stroke(210, 170, 110)
canvas.strokeWeight(8)
canvas.noFill()
canvas.ellipse(px, py, 300, 65)
case "Mars" =>
canvas.fill(210, 70, 50)
canvas.ellipse(px, py, 190, 190)
canvas.fill(160, 40, 30)
canvas.ellipse(px - 30, py + 30, 40, 30)
case "Earth" =>
canvas.fill(30, 120, 220)
canvas.ellipse(px, py, 200, 200)
canvas.fill(50, 160, 60)
canvas.ellipse(px - 30, py + 20, 70, 50)
case _ =>
canvas.fill(190, 195, 200)
canvas.ellipse(px, py, 200, 200)
canvas.fill(150, 155, 160)
canvas.ellipse(px - 40, py + 30, 35, 28)
}
canvas.fill(255, 255, 255)
canvas.text(s"TARGET PLANET: $selectedPlanet", px - 65, py + 130)
if (!isLanded) {
canvas.stroke(255, 0, 0)
canvas.strokeWeight(2)
canvas.noFill()
canvas.ellipse(targetX, targetY, 24, 24)
canvas.line(targetX - 18, targetY, targetX + 18, targetY)
canvas.line(targetX, targetY - 18, targetX, targetY + 18)
}
}
def drawEarthAndLaunchUI(canvas: CanvasDraw) {
canvas.fill(30, 120, 220)
canvas.stroke(10, 60, 160)
canvas.strokeWeight(2)
canvas.ellipse(50, -20, 180, 180)
canvas.fill(220, 20, 20)
canvas.stroke(255, 255, 255)
canvas.strokeWeight(2)
canvas.rect(20, 15, 90, 35)
canvas.fill(255, 255, 255)
canvas.text("LAUNCH", 32, 28)
if (isTimerRunning) {
val sec = countdownTimer.toInt
val msec = ((countdownTimer - sec) * 100).toInt
canvas.fill(255, 215, 0)
if (sec <= 3) {
canvas.text(f"COUNTDOWN: 0$sec%d:$msec%02d MS", 125, 30)
} else {
canvas.text(f"COUNTDOWN: $sec%02d SEC", 125, 30)
}
} else if (isLaunched && !isLanded) {
canvas.fill(51, 204, 51)
// ???? ?????: ??? ??? ?????, ??? ??? ????????????
canvas.text("GOODBYE ISRO, GOODBYE ASTRONAUTS!", 125, 30)
}
}
def drawDetailedFlag(canvas: CanvasDraw) {
if (isLanded) {
val fx = targetX - 30.0
val fy = targetY + 25.0
val fw = 90.0
val fh = 18.0
canvas.stroke(220, 220, 220)
canvas.strokeWeight(3)
canvas.line(fx, fy + fh * 3 + 10, fx, fy - 20)
val stepSize = 3.0
var x = 0.0
while (x < fw) {
val yOffset = math.sin(waveAngle + (x * 0.04)) * 5.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.04)) * 5.0)
val radius = 7.0
canvas.stroke(0, 0, 128)
canvas.strokeWeight(1)
canvas.noFill()
canvas.ellipse(chakraX, chakraY, radius * 2, radius * 2)
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)
}
}
}
def drawISROMissileAndAstronaut(canvas: CanvasDraw) {
val rx = rocketX
val ry = rocketY
if (isLaunched && !isLanded) {
canvas.fill(200, 200, 200, 150)
canvas.noStroke()
canvas.ellipse(rx - 8, ry - 20, random(12, 18), random(12, 18))
canvas.fill(255, 69, 0)
canvas.ellipse(rx, ry - 12, 10, 20)
}
canvas.fill(240, 240, 240)
canvas.stroke(100, 100, 100)
canvas.strokeWeight(1)
canvas.rect(rx - 15, ry, 30, 45)
canvas.fill(255, 153, 51)
canvas.line(rx - 15, ry + 45, rx, ry + 60)
canvas.line(rx + 15, ry + 45, rx, ry + 60)
canvas.fill(0, 51, 102)
canvas.text("ISRO", rx - 12, ry + 32)
if (isLanded) {
val doorWidth = 14.0 * (1.0 - doorOpenProgress)
canvas.fill(50, 50, 50)
canvas.rect(rx - 7, ry + 8, 14, 20)
canvas.fill(180, 180, 180)
canvas.rect(rx - 7, ry + 8, doorWidth, 20)
if (doorOpenProgress > 0.5) {
canvas.stroke(150, 150, 150)
canvas.strokeWeight(3)
canvas.line(rx - 3, ry + 8, rx + 22, ry - 15)
}
// ??? ???????????? (???! ??? ?? ????!)
if (astronautStep > 0) {
val ax = rx + 12 + (astronautStep * 22.0)
val ay = ry - 5 - (astronautStep * 10.0)
canvas.fill(200, 200, 200)
canvas.rect(ax - 7, ay, 4, 14)
canvas.fill(255, 255, 255)
canvas.stroke(80, 80, 80)
canvas.strokeWeight(1)
canvas.rect(ax - 6, ay, 12, 16)
canvas.fill(255, 255, 255)
canvas.ellipse(ax, ay + 20, 14, 14)
canvas.fill(30, 144, 255)
canvas.ellipse(ax + 2, ay + 21, 8, 7)
canvas.stroke(255, 255, 255)
canvas.strokeWeight(3)
canvas.line(ax + 6, ay + 10, ax + 15, ay + 18)
canvas.line(ax - 6, ay + 8, ax - 12, ay + 2)
canvas.line(ax - 3, ay, ax - 6, ay - 10)
canvas.line(ax + 3, ay, ax + 6, ay - 10)
if (astronautStep >= 0.8) {
// "???!" ?????
canvas.fill(255, 255, 255)
canvas.rect(ax + 10, ay + 26, 35, 18)
canvas.fill(0, 0, 0)
canvas.text("???!", ax + 14, ay + 30)
// "?? ????!" ?????
canvas.fill(255, 153, 51)
canvas.rect(ax - 10, ay + 48, 70, 22)
canvas.fill(255, 255, 255)
canvas.text("?? ????! ??", ax - 6, ay + 53)
}
}
}
}
def viewState(canvas: CanvasDraw) {
canvas.fill(5, 5, 20, 50)
canvas.noStroke()
canvas.rect(0, 0, cwidth, cheight)
repeatFor(fireworks) { f => f.view(canvas) }
drawPlanetList(canvas)
if (!isZoomed) {
drawSolarSystem(canvas)
} else {
drawZoomedPlanet(canvas)
}
drawEarthAndLaunchUI(canvas)
drawDetailedFlag(canvas)
drawISROMissileAndAstronaut(canvas)
canvas.fill(255, 153, 51)
canvas.text("INDIAN ISRO ASTRONAUT MISSION", 150, cheight - 20)
}
animateWithCanvasDraw { canvas =>
updateState()
viewState(canvas)
}