Code Sketch
yadnesh shahare
Category: Programming
// --- ISRO ULTIMATE MISSION: MASTERPIECE EDITION (HIGH VISUAL DETAILING) ---
cleari(); originBottomLeft();
// MIDI Safe Initialization
var isGameAudioAllowed = false
try {
setNoteInstrument(Instrument.PIANO)
isGameAudioAllowed = true
} catch {
case e: Exception => println("Audio/MIDI not supported on this device.")
}
def playSoundFx(p: Int, d: Int) = {
if (isGameAudioAllowed) {
try { playNote(p, d) } catch { case _: Exception => }
}
}
var fullJanaGanaTune = ArrayBuffer((53,300),(55,300),(57,300),(57,300),(57,300),(57,300),(57,300),(55,300),(57,300),(58,300),(57,300),(55,300),(53,300),(55,300),(53,500),(60,300),(60,300),(60,300),(58,300),(60,300),(58,300),(57,300),(55,300),(57,300),(58,500),(57,300),(55,300),(53,500),(53,300),(55,300),(57,300),(57,300),(57,300),(57,300),(57,300),(55,300),(57,300),(58,300),(57,300),(55,300),(53,300),(55,300),(53,500),(60,300),(60,300),(60,300),(58,300),(60,300),(58,300),(57,300),(55,300),(57,300),(58,500),(57,300),(55,300),(53,500))
val fullVandeMataramTune = Array((60,400),(62,400),(65,500),(62,400),(60,400),(62,500),(60,400),(62,400),(65,400),(67,400),(69,600),(69,400),(70,400),(69,400),(67,400),(65,400),(67,500),(65,400),(62,400),(60,400),(62,400),(60,600))
var (janaIndex, vandeIndex, charIndex, textDelayTimer) = (0, 0, 0, 0.0)
var (janaGanaFinished, anthemFinished, startAnthemPhase) = (false, false, false)
val fullAnthemText = "Jana-gana-mana-adhinayaka jaya he\nBharata-bhagya-vidhata.\nPunjaba-Sindhu-Gujarata-Maratha\nDravida-Utkala-Banga\nVindhya-Himachala-Yamuna-Ganga\nUchchhala-Jaladhi-taranga\nTava subha name jage, Tava subha asisa mage,\nGaye tava jaya gatha.\nJana-gana-mangala-dayaka jaya he\nBharata-bhagya-vidhata.\nJaya he, jaya he, jaya he,\nJaya jaya jaya, jaya he!\n\n--- VANDE MATARAM ---\nVande Mataram! Sujalam Suphalam\nMalayaja Shytamalam Shasya Shyamalam\nMataram! Vande Mataram!"
def playAnthemStep() {
textDelayTimer += 0.04
if (textDelayTimer >= 0.15) { textDelayTimer = 0.0; if (charIndex < fullAnthemText.length) charIndex += 1 }
if (!janaGanaFinished) {
if (janaIndex < fullJanaGanaTune.length) { val (n, d) = fullJanaGanaTune(janaIndex); playSoundFx(n, d); janaIndex += 1 }
else { fullJanaGanaTune.clear(); janaGanaFinished = true }
} else {
if (vandeIndex < fullVandeMataramTune.length) { val (n, d) = fullVandeMataramTune(vandeIndex); playSoundFx(n, d); vandeIndex += 1 }
else if (charIndex >= fullAnthemText.length) anthemFinished = true
}
}
case class PlanetDetail(name: String, realName: String, surfaceCol: Color, darkSurfCol: Color, accent3D: Color, hasRings: Boolean, gameModeType: Int, infoLine1: String, infoLine2: String, infoLine3: String, infoLine4: String, infoLine5: String, infoLine6: String, infoLine7: String, infoLine8: String, quizQuestion: String, quizOptions: Array[String], correctOpt: Int)
val realSolarSystemMap = Array(
PlanetDetail("Mercury", "Mercury (Budh)", cm.rgb(120,120,120), cm.rgb(60,60,60), cm.rgb(200,200,200), false, 2, " Gravity: 3.7 m/s� | Closest Planet to Sun", " Extreme Temp: Very hot days, freezing nights", " High Orbital Inclination & Delta-V Criteria", " Distance: 57.9 Million km | Orbit: 88 Days", " Radius: 2,439.7 km (~2.44 Million m)", " Mass: 3.301 � 10�� kg | Temp: -180�C to 430�C", " Exosphere: Thin helium & sodium trace", " Surface: Heavily cratered silicate crust", "Which planet is closest to the Sun in our Solar System?", Array("Mercury", "Venus", "Mars", "Earth"), 0),
PlanetDetail("Venus", "Venus (Shukra)", cm.rgb(210,150,80), cm.rgb(100,70,30), cm.rgb(255,200,130), false, 3, " Gravity: 8.87 m/s� | Shukrayaan-1 Target", " Dense Atmosphere: 96.5% Carbon Dioxide", " High-Resolution Synthetic Aperture Radar", " Distance: 108.2 Million km | Orbit: 225 Days", " Radius: 6,051.8 km (~6.05 Million m)", " Mass: 4.867 � 10�? kg | Temp: ~464�C", " Pressure: 92 bar (Supercritical CO2)", " Clouds: Concentrated sulfuric acid droplets", "Which is the hottest planet in the Solar System?", Array("Venus", "Mercury", "Mars", "Jupiter"), 0),
PlanetDetail("Earth", "Earth (Prithvi)", cm.rgb(40,130,240), cm.rgb(20,60,120), cm.rgb(100,200,255), false, 1, " Gravity: 9.81 m/s� | Our Home Planet", " Satellite: Moon (Chandrayaan-3 South Pole)", " Launch Centre: SDSC SHAR, Sriharikota", " Distance: 149.6 Million km (1 AU)", " Radius: 6,371 km (~6.37 Million m)", " Mass: 5.972 � 10�? kg | Temp: -89�C to 58�C", " Atmosphere: 78% Nitrogen, 21% Oxygen", " Biosphere: Only known life-bearing world", "How many days does Earth take to complete one orbit around the Sun?", Array("365 Days", "100 Days", "500 Days", "30 Days"), 0),
PlanetDetail("Mars", "Mars (Mangal)", cm.rgb(200,70,40), cm.rgb(100,30,15), cm.rgb(255,130,100), false, 2, " Gravity: 3.72 m/s� | Mars Orbiter Mission (MOM)", " Launch Vehicle: PSLV-XL C25 Config", " Interplanetary Hohmann Transfer Orbit", " Distance: 227.9 Million km | Orbit: 687 Days", " Radius: 3,389.5 km (~3.39 Million m)", " Mass: 6.417 � 10�� kg | Temp: -125�C to 20�C", " Thin Atmosphere: 95% CO2, low pressure", " Topography: Olympus Mons & Valles Marineris", "Which planet is famously known as the 'Red Planet'?", Array("Mars", "Mercury", "Jupiter", "Saturn"), 0),
PlanetDetail("Jupiter", "Jupiter (Guru)", cm.rgb(210,140,90), cm.rgb(100,60,40), cm.rgb(255,190,140), true, 1, " Gravity: 24.79 m/s� | Largest Planet", " Powerful Magnetic Field & Radiation", " Subsurface Water Ocean on Europa", " Distance: 778.5 Million km | Orbit: 11.8 Years", " Radius: 69,911 km (~69.9 Million m)", " Mass: 1.898 � 10�? kg | Temp: ~ -110�C", " Composition: 90% Hydrogen, 10% Helium", " Great Red Spot: Giant anticyclonic storm", "Which is the largest planet in our Solar System?", Array("Jupiter", "Saturn", "Neptune", "Earth"), 0),
PlanetDetail("Saturn", "Saturn (Shani)", cm.rgb(190,170,110), cm.rgb(90,80,50), cm.rgb(240,230,160), true, 2, " Gravity: 10.44 m/s� | Ringed Planet Jewel", " Titan's Dense Atmosphere & Hydrocarbons", " Active Cryovolcanism on Enceladus", " Distance: 1.4 Billion km | Orbit: 29.5 Years", " Radius: 58,232 km (~58.2 Million m)", " Mass: 5.683 � 10�? kg | Temp: ~ -140�C", " Rings: 99% water ice with silicate dust", " Density: Less than water (0.687 g/cm�)", "Which planet is famous for its bright prominent ring system?", Array("Saturn", "Mars", "Mercury", "Venus"), 0),
PlanetDetail("Uranus", "Uranus (Arun)", cm.rgb(100,200,220), cm.rgb(40,90,100), cm.rgb(180,240,255), true, 3, " Gravity: 8.69 m/s� | Extreme 97.77� Tilt", " Ice Giant with Methane Mantle Overlay", " Off-center Offset Magnetic Axis", " Distance: 2.87 Billion km | Orbit: 84 Years", " Radius: 25,362 km (~25.3 Million m)", " Mass: 8.681 � 10�? kg | Temp: ~ -195�C", " Atmosphere: Hydrogen, helium, methane ice", " Coldest Planetary Atmosphere in Solar System", "Which blue-green ice giant planet has an extreme axial tilt?", Array("Uranus", "Mars", "Venus", "Mercury"), 0),
PlanetDetail("Neptune", "Neptune (Varun)", cm.rgb(50,90,220), cm.rgb(20,40,100), cm.rgb(130,170,255), true, 2, " Gravity: 11.15 m/s� | Outermost Major Planet", " Supersonic Winds: Up to 2,100 km/h", " Retrograde Orbit of Triton Moon", " Distance: 4.5 Billion km | Orbit: 165 Years", " Radius: 24,622 km (~24.6 Million m)", " Mass: 1.024 � 10�? kg | Temp: ~ -200�C", " Dynamic Atmosphere: Great Dark Spot storms", " Triton: Active nitrogen geysers observed", "Which is the farthest major planet from the Sun in our Solar System?", Array("Neptune", "Mars", "Jupiter", "Mercury"), 0)
)
val keplerSolarSystemMap = Array(
PlanetDetail("Kepler-22b", "Kepler-22b (KOI-087.01)", cm.rgb(70,180,150), cm.rgb(30,90,70), cm.rgb(120,240,200), false, 2, " First habitable 'Super-Earth' planet candidate.", " Size: 2.4 times larger than Earth.", " Orbital Distance: 0.85 AU (127 Million km)", " Distance from Earth: ~635 Light Years", " Radius: ~15,290 km (~15.29 Million m)", " Mass: ~9.1 Earth Masses | Temp: -11�C to 22�C", " Planet Type: Potential Ocean World or Mini-Neptune", " Discovery Year: 2011 (Kepler Telescope)", "Because Kepler-22b is larger than Earth, what classification is it given?", Array("Super-Earth", "Mini-Moon", "Small Star", "Flat World"), 0),
PlanetDetail("Kepler-16b", "Kepler-16b (Kepler-16AB b)", cm.rgb(200,160,220), cm.rgb(90,70,110), cm.rgb(245,210,255), true, 3, " Famous 'Tatooine' planet with dual suns.", " Orbits around two stars simultaneously (Circumbinary).", " Gas Giant composition (Saturn-sized).", " Distance from Earth: ~245 Light Years", " Radius: ~53,200 km (~53.2 Million m)", " Mass: ~0.33 Jupiter Mass | Temp: -70�C", " Primary Stars: K-dwarf + M-dwarf pair", " Orbit Period: 229 Days around binary center", "How many host stars does planet Kepler-16b orbit?", Array("2 Stars (Binary)", "1 Star", "5 Stars", "None"), 0),
PlanetDetail("Kepler-186f", "Kepler-186f (KOI-571.05)", cm.rgb(140,210,110), cm.rgb(60,90,45), cm.rgb(200,255,170), false, 2, " First Earth-sized planet in Habitable Zone.", " Potential candidate for liquid surface water.", " High probability of rocky surface terrain.", " Distance from Earth: ~580 Light Years", " Radius: ~7,450 km (~7.45 Million m)", " Mass: ~1.4 Earth Mass | Orbit: 130 Days", " Host Star: Red Dwarf (M1V class)", " Insolation: Receives 32% of Earth's sunlight", "Is planet Kepler-186f located in its star's Habitable Zone?", Array("Yes", "No", "Unknown", "Never"), 0),
PlanetDetail("Kepler-452b", "Kepler-452b (KOI-7016.01)", cm.rgb(90,140,200), cm.rgb(40,70,110), cm.rgb(160,210,255), false, 1, " Famously known as 'Earth's Cousin' (Earth 2.0).", " Orbital year length: 385 Days (Near Earth twin).", " Super-Earth Class rocky/thick atmosphere planet.", " Distance from Earth: ~1,800 Light Years", " Radius: ~10,380 km (~10.38 Million m)", " Mass: ~5 Earth Masses | Temp: ~ -8�C", " Host Star: Kepler-452 (G2V Solar Twin)", " Age: ~6 Billion Years (1.5B years older than Sun)", "What nickname was given to Kepler-452b due to its Earth-like traits?", Array("Earth's Cousin", "Moon Twin", "Sun Twin", "Mars Twin"), 0),
PlanetDetail("Kepler-10b", "Kepler-10b (KOI-072.01)", cm.rgb(220,90,90), cm.rgb(110,40,40), cm.rgb(255,160,160), false, 3, " Extreme 'Lava World' with molten surface.", " Very close proximity to host star.", " Surface temp churns rock/lava (>1,300�C).", " Distance from Earth: ~560 Light Years", " Radius: ~9,360 km (~9.36 Million m)", " Mass: ~3.2 Earth Masses | Orbit: 20 Hours", " Tidal Locking: One side permanently molten", " Density: High silicate and iron core", "What covers the surface of Kepler-10b due to extreme heat?", Array("Molten Lava / Rock", "Ice Mountains", "Cold Water", "Green Forests"), 0),
PlanetDetail("Kepler-62f", "Kepler-62f (KOI-701.04)", cm.rgb(80,190,210), cm.rgb(35,90,100), cm.rgb(150,245,255), false, 1, " Candidate 'Ocean World' covered by global sea.", " Approximately 40% larger than Earth.", " Host Star: K-type Orange Dwarf.", " Distance from Earth: ~1,200 Light Years", " Radius: ~8,980 km (~8.98 Million m)", " Mass: ~2.8 Earth Masses | Orbit: 267 Days", " Climate Model: Stable global ocean with greenhouse gas", " Habitable Index: Very High", "What is Kepler-62f most likely covered by?", Array("A Global Ocean", "Only Sand Deserts", "Gas Only", "Plastic"), 0),
PlanetDetail("Kepler-90i", "Kepler-90i (KOI-351 i)", cm.rgb(230,150,60), cm.rgb(110,70,20), cm.rgb(255,210,130), false, 2, " Part of 8-planet system found by Google AI.", " Discovered via Neural Network Machine Learning.", " Sizzling rocky terrestrial surface.", " Distance from Earth: ~2,840 Light Years", " Radius: ~8,410 km (~8.41 Million m)", " Mass: ~2.5 Earth Masses | Orbit: 14.4 Days", " System Structure: Matches Solar System planet count", " Surface Temp: ~430�C", "Which technology helped discover planet Kepler-90i?", Array("Artificial Intelligence (Google AI)", "Simple Camera", "Microscope", "Newspaper"), 0),
PlanetDetail("K2-18b", "K2-18b (EPIC 201912552 b)", cm.rgb(60,200,180), cm.rgb(20,90,80), cm.rgb(140,255,235), false, 2, " Hycean Planet with hydrogen atmosphere.", " JWST detected water vapor & methane traces.", " Potential liquid ocean beneath atmosphere.", " Distance from Earth: ~124 Light Years", " Radius: ~16,620 km (~16.62 Million m)", " Mass: ~8.6 Earth Masses | Temp: ~ -8�C", " JWST Detection: Carbon-bearing molecules (CO2, CH4)", " Potential Biosignature: DMS trace research", "What trace evidence did the Space Telescope find in K2-18b's atmosphere?", Array("Water Vapor", "Petrol", "Diesel", "Milk"), 0)
)
val starCount = 350
val starX = Array.fill(starCount)(randomDouble(0, cwidth))
val starY = Array.fill(starCount)(randomDouble(0, cheight))
val starSize = Array.fill(starCount)(randomDouble(1.0, 4.0))
var (waveAngle, chakraRotation, neonGlowPhase, globalTime) = (0.0, 0.0, 0.0, 0.0)
var currentSolarSystemId = 1
def getActivePlanetList(): Array[String] = if (currentSolarSystemId == 1) Array("Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune") else Array("Kepler-22b", "Kepler-16b", "Kepler-186f", "Kepler-452b", "Kepler-10b", "Kepler-62f", "Kepler-90i", "K2-18b")
def getActivePlanetDetailsMap(): Array[PlanetDetail] = if (currentSolarSystemId == 1) realSolarSystemMap else keplerSolarSystemMap
var selectedPlanet = "Mars"
var (planetLocked, isTimerRunning, isSpaceTravelling, isLandingOnPlanet, isLaunched, isLanded) = (false, false, false, false, false, false)
var (customAlertMessage, quizFeedback) = ("", "")
var (alertTimer, countdownTimer, spaceTravelProgress, landingProgress, doorOpeningProgress, astroWaitTimer, flagPlantProgress, landingLegProgress) = (0.0, 10.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)
var (rocketCurrentX, rocketCurrentY) = (90.0, cheight - 170.0)
var (astronautOut, infoPanelShown, isFlagPlantedOnPlanet, isAstronautReturningIn, quizActive, isMiniGameActive, readyToReturnEarth) = (false, false, false, false, false, false, false)
var (infoPageNumber, activeGameMode) = (1, 1)
var (astroWalkToPlantX, miniGameTimer) = (0.0, 20.0)
val (plantedFlagX, plantedFlagY) = ((cwidth / 2.0) - 80.0, 155.0)
case class TricolorRibbonNode(var x: Double, var y: Double, var life: Double, col: Color, waveOffset: Double)
val exhaustRibbons = ArrayBuffer.empty[TricolorRibbonNode]
def addTricolorExhaust(x: Double, y: Double) {
val t = globalTime * 14.0
exhaustRibbons.append(TricolorRibbonNode(x - 9 + math.sin(t) * 7, y, 1.0, cm.rgb(255, 153, 51), t))
exhaustRibbons.append(TricolorRibbonNode(x, y, 1.0, cm.rgb(255, 255, 255), t + 2.0))
exhaustRibbons.append(TricolorRibbonNode(x + 9 + math.cos(t) * 7, y, 1.0, cm.rgb(18, 136, 7), t + 4.0))
}
def updateExhaust() {
exhaustRibbons.filterInPlace(_.life > 0)
repeatFor(exhaustRibbons) { p => p.y -= 5.0; p.x += math.sin(globalTime * 12.0 + p.waveOffset) * 3.0; p.life -= 0.045 }
}
var isMiniGameTimerRunning = false
var (devilPlayerX, devilPlayerY, devilPlayerVy, devilPlayerVx) = ((cwidth / 2.0) - 180.0, 130.0, 0.0, 0.0)
var (isGrounded, canDoubleJump, jumpKeyPressedLastFrame, isDevilKeyCollected) = (false, false, false, false)
var (trollKeyX, trollKeyY, exitDoorX) = ((cwidth / 2.0) + 140.0, 140.0, (cwidth / 2.0) - 180.0)
var (dodgerShipX, dodgerShipY) = (cwidth / 2.0, cheight / 2.0 - 50.0)
val dodgerCount = 4
var dodgerAstX = Array.fill(dodgerCount)(cwidth / 2.0)
var dodgerAstY = Array.fill(dodgerCount)(cheight / 2.0 + 150.0)
var dodgerAstSpeed = Array.fill(dodgerCount)(3.8)
var dodgerScore = 0
var (landerX, landerY, landerVy, landerVx, landerFuel) = (cwidth / 2.0, cheight / 2.0 + 50.0, 0.0, 0.0, 100.0)
def resetDodgerGame() {
val gx = cwidth / 2.0 - 220.0; dodgerShipX = cwidth / 2.0; dodgerScore = 0
for (i <- 0 until dodgerCount) { dodgerAstX(i) = gx + 30.0 + randomDouble(0, 380); dodgerAstY(i) = (cheight / 2.0 + 90.0) + (i * 45.0); dodgerAstSpeed(i) = randomDouble(3.0, 5.0) }
}
def resetLanderGame() { landerX = cwidth / 2.0; landerY = cheight / 2.0 + 60.0; landerVy = 0.2; landerVx = 0.0; landerFuel = 100.0 }
var (isReturnTimerRunning, isReturnLaunched, isLandingOnEarth, isLandedOnEarth, isParadeSceneActive, isParadeInPosition) = (false, false, false, false, false, false)
var (returnCountdownTimer, earthLandingProgress, earthAstronautWalkRightProgress) = (5.0, 0.0, 0.0)
var (astroParadeWalkX, armyParadeWalkX) = (-50.0, cwidth + 50.0)
def dieAndResetDevilLevel(msg: String) {
playSoundFx(38, 300); customAlertMessage = s" $msg"; alertTimer = 1.8; miniGameTimer = 20.0; isMiniGameTimerRunning = true
repeatFor(getActivePlanetDetailsMap()) { pd => if (pd.name == selectedPlanet) activeGameMode = pd.gameModeType }
if (activeGameMode == 1) resetDodgerGame()
else if (activeGameMode == 3) resetLanderGame()
else {
val gx = cwidth / 2.0 - 220.0; val gy = cheight / 2.0 - 100.0
devilPlayerX = gx + 30.0; devilPlayerY = gy + 170.0; devilPlayerVy = 0.0; devilPlayerVx = 0.0; isGrounded = false; canDoubleJump = true
trollKeyX = gx + 340.0; isDevilKeyCollected = false; exitDoorX = gx + 40.0
}
}
def updateState() {
if (startAnthemPhase) { waveAngle += 0.22; if (!anthemFinished) playAnthemStep(); return }
waveAngle += 0.22; chakraRotation += 0.22; neonGlowPhase += 0.22; globalTime += 0.025
updateExhaust()
if (alertTimer > 0) { alertTimer -= 0.04; if (alertTimer <= 0) customAlertMessage = "" }
if (isTimerRunning && countdownTimer > 0) { countdownTimer -= 0.04; if (countdownTimer <= 0) { countdownTimer = 0.0; isTimerRunning = false; quizActive = true } }
if (isSpaceTravelling && !isLandingOnPlanet) {
addTricolorExhaust(rocketCurrentX, rocketCurrentY - 20); spaceTravelProgress += 0.005
var (targetX, targetY) = (cwidth / 2.0, cheight / 2.0)
val pList = getActivePlanetList(); val planetSpeeds = Array(0.8, 0.6, 0.45, 0.4, 0.35, 0.28, 0.22, 0.16)
for (i <- pList.indices if pList(i) == selectedPlanet) {
val a = globalTime * (if(i < planetSpeeds.length) planetSpeeds(i) else 0.2)
targetX = (cwidth / 2.0 - 30.0) + math.cos(a) * ((i + 1) * 20.0); targetY = (cheight / 2.0) + math.sin(a) * ((i + 1) * 12.0)
}
val arcOffset = math.sin(spaceTravelProgress * math.Pi) * 90.0
rocketCurrentX = (90.0 + (targetX - 90.0) * spaceTravelProgress) + arcOffset
rocketCurrentY = ((cheight - 170.0) + (targetY - (cheight - 170.0)) * spaceTravelProgress) - arcOffset
if (spaceTravelProgress >= 1.0) { isSpaceTravelling = false; isLandingOnPlanet = true; landingProgress = 0.0; landingLegProgress = 0.0; isLaunched = true; rocketCurrentX = cwidth / 2.0; rocketCurrentY = cheight + 100.0 }
}
if (isLandingOnPlanet && !isLanded) {
addTricolorExhaust(rocketCurrentX, rocketCurrentY - 25); landingProgress += 0.004
if (landingProgress > 0.4 && landingLegProgress < 1.0) landingLegProgress += 0.02
rocketCurrentX = (cwidth / 2.0) + math.sin(landingProgress * math.Pi * 5) * 18.0
rocketCurrentY = (cheight + 100.0) - ((cheight + 100.0) - 175.0) * landingProgress
if (landingProgress >= 1.0) { isLandingOnPlanet = false; isLanded = true; rocketCurrentX = cwidth / 2.0; rocketCurrentY = 175.0; landingLegProgress = 1.0; playSoundFx(45, 250) }
}
if (isLanded && !isReturnLaunched && !isAstronautReturningIn && !isLandingOnEarth && !readyToReturnEarth && !infoPanelShown) {
if (doorOpeningProgress < 1.0) doorOpeningProgress += 0.01
else {
astronautOut = true
if (astroWalkToPlantX < 80.0) astroWalkToPlantX += 1.2
else if (flagPlantProgress < 1.0) { flagPlantProgress += 0.02; if (flagPlantProgress >= 1.0) isFlagPlantedOnPlanet = true }
else { astroWaitTimer += 0.04; if (astroWaitTimer >= 1.2) infoPanelShown = true }
}
}
if (isAstronautReturningIn) {
if (astroWalkToPlantX > 0.0) astroWalkToPlantX -= 1.5
else if (doorOpeningProgress > 0.0) doorOpeningProgress -= 0.02
else { isAstronautReturningIn = false; astronautOut = false; isReturnTimerRunning = true; returnCountdownTimer = 5.0 }
}
if (isReturnTimerRunning && returnCountdownTimer > 0) { returnCountdownTimer -= 0.04; if (returnCountdownTimer <= 0) { returnCountdownTimer = 0.0; isReturnTimerRunning = false; isReturnLaunched = true } }
if (isReturnLaunched && !isLandingOnEarth && !isLandedOnEarth) {
addTricolorExhaust(rocketCurrentX, rocketCurrentY - 20); rocketCurrentY += 5.0
if (rocketCurrentY > cheight + 100.0) { isReturnLaunched = false; isLandingOnEarth = true; earthLandingProgress = 0.0; landingLegProgress = 0.0; rocketCurrentX = cwidth / 2.0; rocketCurrentY = cheight + 100.0 }
}
if (isLandingOnEarth && !isLandedOnEarth) {
addTricolorExhaust(rocketCurrentX, rocketCurrentY - 25); earthLandingProgress += 0.004
if (earthLandingProgress > 0.4 && landingLegProgress < 1.0) landingLegProgress += 0.02
rocketCurrentX = (cwidth / 2.0) + math.sin(earthLandingProgress * math.Pi * 5) * 18.0
rocketCurrentY = (cheight + 100.0) - ((cheight + 100.0) - 175.0) * earthLandingProgress
if (earthLandingProgress >= 1.0) { isLandingOnEarth = false; isLandedOnEarth = true; rocketCurrentX = cwidth / 2.0; rocketCurrentY = 175.0; landingLegProgress = 1.0; doorOpeningProgress = 1.0; astronautOut = true; playSoundFx(40, 250) }
}
if (isLandedOnEarth && !isParadeSceneActive) { earthAstronautWalkRightProgress += 2.8; if (earthAstronautWalkRightProgress > cwidth / 2.0 + 200.0) isParadeSceneActive = true }
if (isParadeSceneActive && !isParadeInPosition) {
if (astroParadeWalkX < (cwidth / 2.0) - 120.0) astroParadeWalkX += 1.6
if (armyParadeWalkX > (cwidth / 2.0) + 120.0) armyParadeWalkX -= 1.6
if (astroParadeWalkX >= (cwidth / 2.0) - 120.0 && armyParadeWalkX <= (cwidth / 2.0) + 120.0) { isParadeInPosition = true; startAnthemPhase = true }
}
if (isMiniGameActive) {
val gx = cwidth / 2.0 - 220.0; val gy = cheight / 2.0 - 100.0
if (isMiniGameTimerRunning) { miniGameTimer -= 0.04; if (miniGameTimer <= 0.0) { miniGameTimer = 0.0; dieAndResetDevilLevel("Time Out! Mission Failed!") } }
if (activeGameMode == 1) {
if (isKeyPressed(Kc.VK_LEFT) && dodgerShipX > gx + 25) dodgerShipX -= 7.5
if (isKeyPressed(Kc.VK_RIGHT) && dodgerShipX < gx + 415) dodgerShipX += 7.5
for (i <- 0 until dodgerCount) {
dodgerAstY(i) -= dodgerAstSpeed(i)
if (math.sqrt(math.pow(dodgerShipX - dodgerAstX(i), 2) + math.pow(dodgerShipY - dodgerAstY(i), 2)) < 22.0) dieAndResetDevilLevel("Asteroid Impact! Ship Crashed!")
if (dodgerAstY(i) < gy + 10) { dodgerAstY(i) = gy + 200.0; dodgerAstX(i) = gx + 30.0 + randomDouble(0, 380); dodgerAstSpeed(i) = randomDouble(3.0, 5.0); dodgerScore += 10; playSoundFx(72, 30) }
}
if (dodgerScore >= 80) { playSoundFx(75, 200); isMiniGameActive = false; isMiniGameTimerRunning = false; readyToReturnEarth = true; customAlertMessage = " Asteroid Belt Cleared! Return Ready!"; alertTimer = 3.5 }
} else if (activeGameMode == 3) {
val padX = gx + 180.0; val padY = gy + 20.0; val padW = 80.0
landerVy -= 0.12; landerY += landerVy; landerX += landerVx
if (isKeyPressed(Kc.VK_UP) && landerFuel > 0) { landerVy += 0.38; landerFuel -= 0.8; playSoundFx(50, 30) }
if (isKeyPressed(Kc.VK_LEFT) && landerFuel > 0) { landerVx -= 0.15; landerFuel -= 0.3 }
if (isKeyPressed(Kc.VK_RIGHT) && landerFuel > 0) { landerVx += 0.15; landerFuel -= 0.3 }
if (landerX < gx + 20) landerX = gx + 20; if (landerX > gx + 420) landerX = gx + 420
if (landerY <= gy + 30) {
if (landerX >= padX && landerX <= padX + padW && math.abs(landerVy) < 1.8) { playSoundFx(80, 250); isMiniGameActive = false; isMiniGameTimerRunning = false; readyToReturnEarth = true; customAlertMessage = " Perfect Smooth Landing Achieved!"; alertTimer = 3.5 }
else dieAndResetDevilLevel("Hard Impact! Lander Crashed!")
}
} else {
val floorY = gy + 170.0
if (isKeyPressed(Kc.VK_RIGHT) && devilPlayerX < gx + 410) devilPlayerX += 5.5
if (isKeyPressed(Kc.VK_LEFT) && devilPlayerX > gx + 15) devilPlayerX -= 5.5
val upPressedNow = isKeyPressed(Kc.VK_UP)
if (upPressedNow && !jumpKeyPressedLastFrame) {
if (isGrounded) { devilPlayerVy = -10.8; isGrounded = false; canDoubleJump = true; playSoundFx(60, 50) }
else if (canDoubleJump) { devilPlayerVy = -10.8 * 0.9; canDoubleJump = false; playSoundFx(67, 50) }
}
jumpKeyPressedLastFrame = upPressedNow
devilPlayerVy += 0.45; devilPlayerY += devilPlayerVy; devilPlayerX += devilPlayerVx; devilPlayerVx *= 0.90
if (devilPlayerX < gx + 15) devilPlayerX = gx + 15; if (devilPlayerX > gx + 410) devilPlayerX = gx + 410
if (devilPlayerY >= floorY) { devilPlayerY = floorY; devilPlayerVy = 0.0; devilPlayerVx = 0.0; isGrounded = true; canDoubleJump = true } else isGrounded = false
if (!isDevilKeyCollected && math.abs(devilPlayerX - trollKeyX) < 25 && math.abs(devilPlayerY - trollKeyY) < 25) { isDevilKeyCollected = true; playSoundFx(80, 80) }
if (isDevilKeyCollected && math.abs(devilPlayerX - exitDoorX) < 30 && math.abs(devilPlayerY - (gy + 140)) < 35) { playSoundFx(78, 200); isMiniGameActive = false; isMiniGameTimerRunning = false; readyToReturnEarth = true; customAlertMessage = " Rover Adventure Complete!"; alertTimer = 3.5 }
}
}
}
def drawTricolorExhaustRibbons(canvas: CanvasDraw) {
repeatFor(exhaustRibbons) { p =>
canvas.fill(p.col.getRed, p.col.getGreen, p.col.getBlue, (p.life * 245).toInt)
canvas.noStroke(); canvas.ellipse(p.x, p.y, p.life * 14.0, p.life * 7.0)
}
}
def drawFullSolarSystem(canvas: CanvasDraw) {
val (centerX, centerY) = (cwidth / 2.0 - 20.0, cheight / 2.0 - 10.0)
canvas.noFill(); val pList = getActivePlanetList()
for (i <- pList.indices) {
canvas.stroke(0, 220, 255, (120 + math.sin(globalTime * 2 + i) * 60).toInt)
canvas.strokeWeight(1.8)
canvas.ellipse(centerX, centerY, (i * 20.0 + 35.0) * 2, (i * 12.0 + 20.0) * 2)
}
val sunGlow = (math.sin(globalTime * 6) * 10 + 68).toFloat
if (currentSolarSystemId == 1) canvas.fill(255, 150, 0) else canvas.fill(255, 230, 60)
canvas.stroke(255, 230, 0); canvas.strokeWeight(10.0); canvas.ellipse(centerX, centerY, sunGlow, sunGlow)
canvas.fill(255, 255, 220); canvas.noStroke(); canvas.ellipse(centerX - 8, centerY + 8, 24, 24)
val planetSpeeds = Array(0.8, 0.6, 0.45, 0.4, 0.35, 0.28, 0.22, 0.16); val activeMap = getActivePlanetDetailsMap()
for (i <- pList.indices) {
val planetName = pList(i); val angle = globalTime * (if(i < planetSpeeds.length) planetSpeeds(i) else 0.2)
val curX = centerX + math.cos(angle) * (i * 20.0 + 35.0); val curY = centerY + math.sin(angle) * (i * 12.0 + 20.0)
var (pCol, pRing) = (cm.rgb(200, 200, 200), false)
repeatFor(activeMap) { pd => if (pd.name == planetName) { pCol = pd.surfaceCol; pRing = pd.hasRings } }
if (pRing) { canvas.noFill(); canvas.stroke(245, 220, 180, 230); canvas.strokeWeight(3.5); canvas.ellipse(curX, curY, 34, 14) }
val pSize = if (Array("Earth", "Kepler-22b", "Kepler-452b").contains(planetName)) 16.0 else (11.0 + (i * 0.3))
canvas.fill(pCol); canvas.stroke(255, 255, 255); canvas.strokeWeight(1.5); canvas.ellipse(curX, curY, pSize, pSize)
if (!planetLocked && isMousePressed && math.abs(mouseX - curX) < 20 && math.abs(mouseY - curY) < 20) {
if (planetName == "Earth") { selectedPlanet = "Earth"; customAlertMessage = "You are already on Earth!"; alertTimer = 3.0 } else selectedPlanet = planetName
}
if (planetName == selectedPlanet) { canvas.noFill(); canvas.stroke(0, 255, 255); canvas.strokeWeight(3.5 + math.sin(neonGlowPhase * 5).toFloat); canvas.ellipse(curX, curY, pSize + 15, pSize + 15) }
}
}
def drawPlanetList(canvas: CanvasDraw) {
canvas.fill(15, 20, 45, 245); canvas.stroke(0, 255, 255); canvas.strokeWeight(2.5); canvas.rect(10, 10, 230, 380)
canvas.fill(255, 255, 255); canvas.text("Select Planet", 15, 30)
canvas.fill(0, 140, 220); canvas.stroke(255, 255, 255); canvas.strokeWeight(1.5); canvas.rect(15, 40, 220, 28)
canvas.fill(255, 255, 255); canvas.text(if (currentSolarSystemId == 1) " System: Real Solar" else " System: Kepler Planet", 18, 59)
if (isMousePressed && mouseX >= 15 && mouseX <= 235 && mouseY >= 40 && mouseY <= 68) {
currentSolarSystemId = if (currentSolarSystemId == 1) 2 else 1
selectedPlanet = if (currentSolarSystemId == 1) "Mars" else "Kepler-22b"
customAlertMessage = if (currentSolarSystemId == 1) "Real Solar System Selected!" else "Kepler Exoplanet System Selected!"
alertTimer = 2.5
}
val activeMap = getActivePlanetDetailsMap(); val pList = getActivePlanetList()
for (i <- pList.indices) {
val py = 88.0 + (i * 32.0); var rName = pList(i)
repeatFor(activeMap) { pd => if (pd.name == pList(i)) rName = pd.realName }
if (!planetLocked && isMousePressed && mouseX >= 15 && mouseX <= 235 && mouseY >= py - 12 && mouseY <= py + 12) {
if (pList(i) == "Earth") { selectedPlanet = "Earth"; customAlertMessage = "You are already on Earth!"; alertTimer = 2.5 } else selectedPlanet = pList(i)
}
if (pList(i) == selectedPlanet) { canvas.fill(0, 180, 80); canvas.rect(15, py - 12, 220, 26); canvas.fill(255, 255, 255) } else canvas.fill(210, 210, 210)
canvas.text(s" $rName", 18, py)
}
}
def draw3DPlanetPreview(canvas: CanvasDraw) {
val (boxX, boxY, boxW, boxH) = (cwidth - 250.0, 15.0, 235.0, 225.0)
canvas.fill(15, 20, 45, 245); canvas.stroke(0, 255, 255); canvas.strokeWeight(2.0); canvas.rect(boxX, boxY, boxW, boxH)
canvas.fill(255, 255, 255); canvas.text(s"3D Preview: $selectedPlanet", boxX + 12, boxY + 22)
val (cx, cy) = (boxX + boxW / 2.0, boxY + boxH / 2.0 + 15.0)
var (pCol, pAccent, pRings) = (cm.rgb(200, 70, 40), cm.rgb(255, 130, 100), false)
repeatFor(getActivePlanetDetailsMap()){ pd => if (pd.name == selectedPlanet) { pCol = pd.surfaceCol; pAccent = pd.accent3D; pRings = pd.hasRings } }
if (pRings) { canvas.noFill(); canvas.stroke(220, 210, 180, 230); canvas.strokeWeight(7.5); canvas.ellipse(cx, cy, 185, 54) }
canvas.fill(pCol); canvas.stroke(pAccent); canvas.strokeWeight(3.0); canvas.ellipse(cx, cy, 115, 115)
canvas.fill(0, 0, 0, 120); canvas.noStroke(); canvas.ellipse(cx + 20 + math.sin(globalTime * 3) * 5.0, cy - 10, 85, 85)
canvas.fill(255, 255, 255, 60); canvas.ellipse(cx - 25, cy - 25, 30, 15)
}
def drawPlanetSurfaceBackground(canvas: CanvasDraw) {
var (surfCol, darkSurfCol) = (cm.rgb(100, 30, 15), cm.rgb(50, 10, 5))
repeatFor(getActivePlanetDetailsMap()){ pd => if (pd.name == selectedPlanet) { surfCol = pd.surfaceCol; darkSurfCol = pd.darkSurfCol } }
canvas.fill(surfCol); canvas.noStroke(); canvas.rect(0, 0, cwidth, 140)
// Enhanced Craters / Detailing on Surface
canvas.fill(darkSurfCol);
canvas.ellipse(120, 40, 50, 15); canvas.ellipse(420, 60, 80, 20); canvas.ellipse(650, 45, 60, 18);
canvas.fill(darkSurfCol); canvas.rect(0, 120, cwidth, 25)
if (isFlagPlantedOnPlanet) drawWavingTricolorFlagWithAshokChakra(canvas, plantedFlagX, plantedFlagY)
}
def drawWavingTricolorFlagWithAshokChakra(canvas: CanvasDraw, fx: Double, fy: Double) {
val (fw, fh) = (52.0, 10.0); canvas.stroke(230, 230, 230); canvas.strokeWeight(3.5); canvas.line(fx, fy + 45, fx, fy - 12)
var x = 0.0; while (x < fw) {
val yOffset = math.sin(waveAngle + (x * 0.12)) * 4.5; canvas.strokeWeight(2.8)
canvas.stroke(255, 153, 51); 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 += 2.0
}
val (chakraX, chakraY) = (fx + 26.0, fy + fh + 2.0 + math.sin(waveAngle + (26.0 * 0.12)) * 4.5)
canvas.fill(0, 0, 190); canvas.noStroke(); canvas.ellipse(chakraX, chakraY, 8.5, 8.5); canvas.stroke(255, 255, 255); canvas.strokeWeight(0.6); canvas.point(chakraX, chakraY)
}
def drawPersonCharacter(canvas: CanvasDraw, px: Double, py: Double, isArmy: Boolean, isSaluting: Boolean) {
canvas.pushMatrix(); canvas.translate(px, py)
val stepSwing = if (startAnthemPhase) 0.0 else math.sin(globalTime * 10) * 5.5
canvas.stroke(if (isArmy) cm.rgb(35, 65, 22) else cm.rgb(190, 190, 210)); canvas.strokeWeight(5.5)
canvas.line(-5, 0, -6 + stepSwing, -22); canvas.line(5, 0, 6 - stepSwing, -22)
canvas.fill(15, 15, 15); canvas.noStroke(); canvas.rect(-9, -25, 7, 4); canvas.rect(3, -25, 7, 4)
canvas.fill(if (isArmy) cm.rgb(80, 110, 50) else cm.rgb(245, 245, 255)); canvas.stroke(0, 255, 255); canvas.strokeWeight(1.5); canvas.rect(-10, 0, 20, 32)
canvas.fill(if (isArmy) cm.rgb(215, 165, 125) else cm.rgb(255, 255, 255)); canvas.ellipse(0, 42, 18, 18)
if (isArmy) { canvas.fill(50, 80, 30); canvas.rect(-10, 48, 20, 6) } else { canvas.fill(0, 190, 250); canvas.ellipse(0, 42, 10, 8) }
canvas.stroke(if (isArmy) cm.rgb(80, 110, 50) else cm.rgb(230, 230, 240)); canvas.strokeWeight(4.5)
if (isSaluting) { canvas.line(-8, 22, -12, 4); canvas.line(8, 22, 14, 34); canvas.line(14, 34, 8, 44) } else { canvas.line(-8, 22, -12, 4); canvas.line(8, 22, 12, 4) }
canvas.popMatrix()
}
def drawParadeGroundScene(canvas: CanvasDraw) {
canvas.fill(34, 139, 34); canvas.noStroke(); canvas.rect(0, 0, cwidth, 140); canvas.fill(25, 95, 25); canvas.rect(0, 125, cwidth, 25)
val (fx, fy, fw, fh) = (cwidth / 2.0 - 70.0, cheight / 2.0 + 10.0, 140.0, 26.0); canvas.stroke(230, 230, 230); canvas.strokeWeight(6.5); canvas.line(fx, fy + fh * 3 + 20, fx, fy - 140)
var x = 0.0; while (x < fw) {
val yOffset = math.sin(waveAngle + (x * 0.05)) * 8.5; canvas.strokeWeight(5.2)
canvas.stroke(255, 153, 51); 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 += 4.0
}
canvas.fill(0, 0, 190); canvas.noStroke(); canvas.ellipse(fx + 70.0, fy + fh + 2.0 + math.sin(waveAngle + 3.5) * 8.5, 19, 19)
for (i <- 0 until 3) { drawPersonCharacter(canvas, astroParadeWalkX - (i * 35.0), 165.0, false, isParadeInPosition); drawPersonCharacter(canvas, armyParadeWalkX + (i * 35.0), 165.0, true, isParadeInPosition) }
drawPatrioticFullText(canvas)
}
def drawEarthFirstLandingScene(canvas: CanvasDraw) {
canvas.fill(34, 139, 34); canvas.noStroke(); canvas.rect(0, 0, cwidth, 140); canvas.fill(30, 110, 210); canvas.rect(0, 125, cwidth, 25); drawISRORocket(canvas)
if (isLandedOnEarth) drawPersonCharacter(canvas, rocketCurrentX + earthAstronautWalkRightProgress, 165.0, false, false)
}
def drawLaunchAndUI(canvas: CanvasDraw) {
if (!isSpaceTravelling && !isLaunched) {
val (btnX, btnY) = (cwidth - 250.0, 250.0)
if (!isTimerRunning && !quizActive) {
canvas.fill(255, 90, 0); canvas.stroke(255, 230, 0); canvas.strokeWeight((math.sin(neonGlowPhase * 4) * 2 + 4.0).toFloat); canvas.rect(btnX, btnY, 235, 45)
canvas.fill(255, 255, 255); canvas.text("? Launch ISRO Mission", btnX + 22, btnY + 28)
if (isMousePressed && mouseX >= btnX && mouseX <= btnX + 235 && mouseY >= btnY && mouseY <= btnY + 45) { planetLocked = true; isTimerRunning = true; countdownTimer = 10.0 }
}
if (isTimerRunning) { canvas.fill(255, 215, 0); canvas.text(s"Launch Countdown: ${countdownTimer.toInt}s", btnX + 15, btnY + 28) }
}
if (readyToReturnEarth && !isReturnLaunched && !isAstronautReturningIn && !isLandingOnEarth) {
canvas.fill(18, 136, 7); canvas.stroke(0, 255, 160); canvas.strokeWeight((math.sin(neonGlowPhase * 4) * 2 + 5.0).toFloat); canvas.rect(cwidth / 2.0 - 120, 25, 240, 45)
canvas.fill(255, 255, 255); canvas.text("? Return to Earth", cwidth / 2.0 - 85, 52)
if (isMousePressed && mouseX >= cwidth / 2.0 - 120 && mouseX <= cwidth / 2.0 + 120 && mouseY >= 25 && mouseY <= 70) isAstronautReturningIn = true
}
if (isReturnTimerRunning) { canvas.fill(255, 215, 0); canvas.text(s"Return Time: ${returnCountdownTimer.toInt}s", cwidth / 2.0 - 110, 80) }
}
def drawISRORocket(canvas: CanvasDraw) {
canvas.pushMatrix(); canvas.translate(rocketCurrentX, rocketCurrentY)
if (!isSpaceTravelling && !isLaunched) { canvas.fill(255, 255, 255); canvas.text("ISRO", -18, 48) }
canvas.fill(245, 245, 255); canvas.stroke(0, 255, 255); canvas.strokeWeight(2.8); canvas.rect(-12, -45, 24, 45)
canvas.fill(255, 65, 65); canvas.stroke(255, 210, 210); canvas.strokeWeight(2.0); canvas.beginShape(); canvas.vertex(0, 25); canvas.vertex(-12, 0); canvas.vertex(12, 0); canvas.endShape()
canvas.fill(225, 225, 235); canvas.stroke(100, 100, 130); canvas.rect(-20, -35, 7, 35); canvas.rect(13, -35, 7, 35)
canvas.stroke(210, 210, 210); canvas.strokeWeight(3.8)
canvas.line(-12, -40, -12 - (landingLegProgress * 15), -45 - (landingLegProgress * 15))
canvas.line(-12 - (landingLegProgress * 15), -45 - (landingLegProgress * 15), -12 - (landingLegProgress * 22), -45 - (landingLegProgress * 15))
canvas.line(12, -40, 12 + (landingLegProgress * 15), -45 - (landingLegProgress * 15))
canvas.line(12 + (landingLegProgress * 15), -45 - (landingLegProgress * 15), 12 + (landingLegProgress * 22), -45 - (landingLegProgress * 15))
if (isLanded && !isParadeSceneActive) {
canvas.fill(40, 40, 55); canvas.rect(-8, -30, 16, 20.0 * doorOpeningProgress)
if (flagPlantProgress > 0.0 && !isFlagPlantedOnPlanet) drawWavingTricolorFlagWithAshokChakra(canvas, -80.0, -20.0)
if (astronautOut && !isLandedOnEarth) {
canvas.pushMatrix(); canvas.translate(-astroWalkToPlantX, -30.0)
drawAstronautPlayer(canvas, 0, 0)
if (astroWalkToPlantX >= 80.0 && flagPlantProgress < 1.0) { canvas.stroke(255, 255, 255); canvas.strokeWeight(3.0); canvas.line(-5, 0, -15, 10) }
canvas.popMatrix()
}
}
canvas.popMatrix()
}
def drawAstronautPlayer(canvas: CanvasDraw, px: Double, py: Double) {
canvas.fill(245, 245, 255); canvas.stroke(0, 255, 255); canvas.strokeWeight(1.5); canvas.rect(px - 8, py - 12, 16, 24)
canvas.fill(255, 255, 255); canvas.ellipse(px, py - 18, 14, 14); canvas.fill(0, 190, 250); canvas.noStroke(); canvas.ellipse(px, py - 18, 9, 7)
}
def drawQuizPopup(canvas: CanvasDraw) {
if (quizActive) {
val (qx, qy) = (cwidth / 2.0 - 225.0, cheight / 2.0 - 130.0)
canvas.fill(15, 20, 45, 250); canvas.stroke(255, 215, 0); canvas.strokeWeight(3.5); canvas.rect(qx, qy, 450, 260)
canvas.fill(255, 255, 255); canvas.text(s"ISRO Quiz: $selectedPlanet", qx + 20, qy + 25)
var qText = ""; var opts = Array("A", "B", "C", "D"); var corr = 0
repeatFor(getActivePlanetDetailsMap()){ pd => if (pd.name == selectedPlanet) { qText = pd.quizQuestion; opts = pd.quizOptions; corr = pd.correctOpt } }
canvas.fill(255, 225, 110); canvas.text(qText, qx + 15, qy + 52)
for (i <- opts.indices) {
val optY = qy + 75.0 + (i * 32.0); canvas.fill(30, 45, 85); canvas.stroke(0, 255, 255); canvas.strokeWeight(1.5); canvas.rect(qx + 15, optY, 420, 26)
canvas.fill(255, 255, 255); canvas.text(opts(i), qx + 25, optY + 18)
if (isMousePressed && mouseX >= qx + 15 && mouseX <= qx + 435 && mouseY >= optY && mouseY <= optY + 26) {
if (i == corr) { quizActive = false; isSpaceTravelling = true; spaceTravelProgress = 0.0; customAlertMessage = "Correct Answer! Mission Continues!"; alertTimer = 3.0 }
else quizFeedback = "Incorrect Answer! Try Again."
}
}
if (quizFeedback != "") { canvas.fill(255, 60, 60); canvas.text(quizFeedback, qx + 20, qy + 235) }
}
}
def drawPlanetInfoPopup(canvas: CanvasDraw) {
if (infoPanelShown) {
val (ix, iy) = (cwidth / 2.0 - 230.0, cheight / 2.0 - 130.0)
canvas.fill(15, 20, 45, 250); canvas.stroke(0, 255, 255); canvas.strokeWeight(3.5); canvas.rect(ix, iy, 460, 260)
var rName = selectedPlanet; val activeMap = getActivePlanetDetailsMap()
repeatFor(activeMap){ pd => if (pd.name == selectedPlanet) rName = pd.realName }
canvas.fill(255, 215, 0); canvas.text(s" Mission Info: $rName (Page $infoPageNumber/3)", ix + 20, iy + 25)
var (l1, l2, l3, l4, l5, l6, l7, l8) = ("", "", "", "", "", "", "", "")
repeatFor(activeMap){ pd => if (pd.name == selectedPlanet) { l1 = pd.infoLine1; l2 = pd.infoLine2; l3 = pd.infoLine3; l4 = pd.infoLine4; l5 = pd.infoLine5; l6 = pd.infoLine6; l7 = pd.infoLine7; l8 = pd.infoLine8 } }
if (infoPageNumber == 1) { canvas.fill(100, 225, 255); canvas.text(" Primary Planetary Characteristics:", ix + 20, iy + 52); canvas.fill(225, 225, 245); canvas.text(l1, ix + 20, iy + 80); canvas.text(l2, ix + 20, iy + 110); canvas.text(l3, ix + 20, iy + 140) }
else if (infoPageNumber == 2) { canvas.fill(100, 255, 210); canvas.text(" Real Scientific & Distance Data:", ix + 20, iy + 52); canvas.fill(225, 225, 245); canvas.text(l4, ix + 20, iy + 80); canvas.text(l5, ix + 20, iy + 110); canvas.text(l6, ix + 20, iy + 140) }
else { canvas.fill(255, 190, 110); canvas.text(" Atmospheric Spectrum & ISRO Notes:", ix + 20, iy + 52); canvas.fill(225, 225, 245); canvas.text(l7, ix + 20, iy + 80); canvas.text(l8, ix + 20, iy + 110) }
canvas.fill(45, 110, 210); canvas.rect(ix + 20, iy + 195, 100, 35); canvas.fill(255, 255, 255); canvas.text("Page ?", ix + 35, iy + 218)
if (isMousePressed && mouseX >= ix + 20 && mouseX <= ix + 120 && mouseY >= iy + 195 && mouseY <= iy + 230) infoPageNumber = if (infoPageNumber == 3) 1 else infoPageNumber + 1
canvas.fill(0, 190, 90); canvas.rect(ix + 140, iy + 195, 150, 35); canvas.fill(255, 255, 255); canvas.text(" Play Game", ix + 170, iy + 218)
if (isMousePressed && mouseX >= ix + 140 && mouseX <= ix + 290 && mouseY >= iy + 195 && mouseY <= iy + 230) { infoPanelShown = false; isMiniGameActive = true; dieAndResetDevilLevel("Game Started!") }
canvas.fill(190, 45, 45); canvas.rect(ix + 300, iy + 195, 130, 35); canvas.fill(255, 255, 255); canvas.text("Close X", ix + 325, iy + 218)
if (isMousePressed && mouseX >= ix + 300 && mouseX <= ix + 430 && mouseY >= iy + 195 && mouseY <= iy + 230) infoPanelShown = false
}
}
def drawCustomAlertPopup(canvas: CanvasDraw) {
if (alertTimer > 0 && customAlertMessage != "") {
canvas.fill(230, 35, 35, 240); canvas.stroke(255, 255, 255); canvas.strokeWeight(2.2); canvas.rect(cwidth / 2.0 - 210.0, 80.0, 420, 50)
canvas.fill(255, 255, 255); canvas.text(customAlertMessage, cwidth / 2.0 - 195.0, 110.0)
}
}
def drawMiniGames(canvas: CanvasDraw) {
if (isMiniGameActive) {
val (gx, gy) = (cwidth / 2.0 - 220.0, cheight / 2.0 - 100.0)
canvas.fill(10, 10, 25, 250); canvas.stroke(0, 255, 210); canvas.strokeWeight(3.5); canvas.rect(gx, gy, 440, 210)
canvas.fill(255, 65, 65); canvas.text(s" Time: ${miniGameTimer.toInt}s", gx + 290, gy + 190)
if (activeGameMode == 1) {
canvas.fill(255, 255, 255); canvas.text(s" Asteroid Dodger | Score: $dodgerScore/80", gx + 15, gy + 190)
canvas.fill(0, 255, 210); canvas.stroke(255, 255, 255); canvas.strokeWeight(1.5)
canvas.beginShape(); canvas.vertex(dodgerShipX, dodgerShipY + 12); canvas.vertex(dodgerShipX - 12, dodgerShipY - 12); canvas.vertex(dodgerShipX + 12, dodgerShipY - 12); canvas.endShape()
canvas.fill(190, 110, 70); canvas.stroke(255, 190, 110); canvas.strokeWeight(1.5)
for (i <- 0 until dodgerCount) canvas.ellipse(dodgerAstX(i), dodgerAstY(i), 22, 22)
} else if (activeGameMode == 3) {
val (padX, padY, padW) = (gx + 180.0, gy + 20.0, 80.0)
canvas.fill(255, 255, 255); canvas.text(s" Lander Fuel: ${landerFuel.toInt}%", gx + 15, gy + 190)
canvas.fill(0, 255, 110); canvas.rect(padX, padY, padW, 8); canvas.fill(255, 255, 255); canvas.text("TARGET PAD", padX + 5, padY + 18)
canvas.fill(255, 210, 0); canvas.stroke(255, 255, 255); canvas.strokeWeight(1.5); canvas.rect(landerX - 12, landerY - 12, 24, 24)
if (isKeyPressed(Kc.VK_UP) && landerFuel > 0) { canvas.fill(255, 110, 0); canvas.noStroke(); canvas.ellipse(landerX, landerY - 20, 10, 16) }
} else {
canvas.fill(255, 255, 255); canvas.text(s" Rover Adventure Game", gx + 15, gy + 190)
canvas.fill(255, 153, 51); canvas.rect(gx + 15, gy + 170, 410, 12)
if (!isDevilKeyCollected) { canvas.fill(255, 215, 0); canvas.ellipse(trollKeyX, trollKeyY, 16, 16) }
canvas.fill(if (isDevilKeyCollected) cm.rgb(0, 255, 160) else cm.rgb(110, 110, 110)); canvas.rect(exitDoorX, gy + 135, 30, 40)
drawAstronautPlayer(canvas, devilPlayerX, devilPlayerY)
}
}
}
def drawPatrioticFullText(canvas: CanvasDraw) {
if (charIndex > 0) {
val lines = fullAnthemText.substring(0, charIndex).split("\n"); var startY = cheight - 40.0
for (i <- lines.indices) {
canvas.fill(255, 215, 0, 110); canvas.text(lines(i), 21.0, startY - 1)
canvas.fill(255, 255, 255); canvas.text(lines(i), 20.0, startY); startY -= 18.0
}
}
}
def drawCleanEndScreen(canvas: CanvasDraw) {
canvas.fill(0, 0, 0); canvas.noStroke(); canvas.rect(0, 0, cwidth, cheight)
val (centerX, centerY) = (cwidth / 2.0, cheight / 2.0); val glowFactor = (math.sin(globalTime * 5) * 2 + 4.0).toFloat
canvas.fill(255, 215, 0); canvas.stroke(255, 160, 0); canvas.strokeWeight(glowFactor); canvas.text("Thank You! Mission Complete", centerX - 110.0, centerY + 60.0)
canvas.fill(0, 255, 255); canvas.stroke(0, 190, 255); canvas.strokeWeight(glowFactor * 0.8); canvas.text("Made by Yadnesh Shahare and Bhavesh Shahare", centerX - 200.0, centerY)
canvas.fill(255, 255, 255); canvas.stroke(255, 255, 255); canvas.strokeWeight(glowFactor * 0.5); canvas.text("Jai Hind! Jai Bharat!", centerX - 80.0, centerY - 60.0)
}
def viewState(canvas: CanvasDraw) { password()
if (anthemFinished) drawCleanEndScreen(canvas)
else {
canvas.fill(0, 0, 0, 255); canvas.noStroke(); canvas.rect(0, 0, cwidth, cheight)
for (i <- 0 until starCount) {
canvas.stroke(255, 255, 255)
canvas.strokeWeight(starSize(i) + (math.sin(globalTime * 5 + i).toFloat * 0.9))
canvas.point(starX(i), starY(i))
}
drawTricolorExhaustRibbons(canvas)
if (isParadeSceneActive) drawParadeGroundScene(canvas)
else if (isLandingOnEarth || isLandedOnEarth) drawEarthFirstLandingScene(canvas)
else {
if (isLaunched) drawPlanetSurfaceBackground(canvas)
else { drawFullSolarSystem(canvas); drawPlanetList(canvas); draw3DPlanetPreview(canvas) }
drawLaunchAndUI(canvas); drawISRORocket(canvas)
}
drawQuizPopup(canvas); drawPlanetInfoPopup(canvas); drawMiniGames(canvas); drawCustomAlertPopup(canvas)
}
}
animateWithCanvasDraw { canvas => updateState(); viewState(canvas) }