Code Sketch


yadnesh shahare
By: Mhalsakant School
Category: Programming
// --- ISRO ULTIMATE MISSION: DUAL SOLAR SYSTEM EDITION (ADVANCED & ENHANCED) ---
cleari(); originBottomLeft(); setNoteInstrument(Instrument.PIANO)

var isGameAudioAllowed = false 
def playSoundFx(pitch: Int, duration: Int) { if (isGameAudioAllowed) playNote(pitch, duration) }

// ?? ?? ?? ??? ???? ????????? ???????? ????? ???
val fullJanaGanaTune = Array((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((53,300),(57,300),(60,300),(60,300),(58,300),(57,300),(55,300),(57,300),(60,500),(65,400),(63,300),(60,300),(57,500))

var tuneIndex = 0; var anthemFinished = false; var charIndex = 0; var textDelayTimer = 0.0
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---\nVande Mataram! Sujalam suphalam malayaja shitalam,\nShasyashyamalam mataram!"

var startAnthemPhase = false; var isVandeMataramPlaying = false

def playJanaGanaStep() {
  textDelayTimer += 0.04
  if (textDelayTimer >= 0.15) { textDelayTimer = 0.0; if (charIndex < fullAnthemText.length) charIndex += 1 }
  
  if (!isVandeMataramPlaying) {
    if (tuneIndex < fullJanaGanaTune.length) { 
      isGameAudioAllowed = true; val (n, d) = fullJanaGanaTune(tuneIndex); playSoundFx(n, d); tuneIndex += 1 
    } else {
      isVandeMataramPlaying = true; tuneIndex = 0
    }
  } else {
    if (tuneIndex < fullVandeMataramTune.length) {
      isGameAudioAllowed = true; val (n, d) = fullVandeMataramTune(tuneIndex); playSoundFx(n, d); tuneIndex += 1
    } else if (charIndex >= fullAnthemText.length) {
      anthemFinished = true
    }
  }
}

case class PlanetDetail(name: String, surfaceCol: Color, darkSurfCol: Color, accent3D: Color, hasRings: Boolean, gameModeType: Int, info: Array[String], qText: String, qOpts: Array[String], correctOpt: Int)

val realSolarSystemMap = Array(
  PlanetDetail("Sun", cm.rgb(255, 140, 0), cm.rgb(120, 60, 0), cm.rgb(255, 220, 100), false, 2, Array("? Advanced ISRO Solar Mission: Aditya-L1", "? Gravity: 274.0 m/s� | Core Temp: 15 Million �C", "? Surface Temp: 5,500�C | Primary Star", "? VELC & SUIT Advanced Payloads Integration", "? Sun-Earth L1 Lagrange Point Halo Orbit", "? X-ray Solar Spectrometer: HEL1OS Payload"), "Which Aditya-L1 payload studies solar eruptions?", Array("SUIT", "VELC", "PAPA", "HEL1OS"), 1),
  PlanetDetail("Mercury", cm.rgb(120, 120, 120), cm.rgb(60, 60, 60), cm.rgb(200, 200, 200), false, 2, Array("? Advanced Deep Space Navigation", "? Gravity: 3.7 m/s� | Closest Planet to Sun", "? Extreme Temp Control Systems", "? BepiColombo ESA-JAXA Advanced Tracking", "? Thin Exosphere: Traces of Sodium & Oxygen", "? Large Metallic Core: Radius ~2,000 km"), "Why is sending an orbiter to Mercury difficult?", Array("Intense solar radiation and high delta-v needs", "Thick atmospheric drag", "Magnetic field reversals", "Lack of water"), 0),
  PlanetDetail("Venus", cm.rgb(210, 150, 80), cm.rgb(100, 70, 30), cm.rgb(255, 200, 130), false, 2, Array("? ISRO Shukrayaan-1 Advanced Radar Mission", "? Gravity: 8.87 m/s� | Dense Atmosphere Control", "? High-Resolution Synthetic Aperture Radar", "? Intense Greenhouse Effect & Extreme Heat Management", "? Toxic Clouds: Concentrated Sulfuric Acid", "? Retrograde Rotation: 243-day spin period"), "What primary radar payload will ISRO use in Shukrayaan-1?", Array("S-band SAR", "Dual-frequency Synthetic Aperture Radar", "Lidar Profiler", "X-ray Spectrometer"), 1),
  PlanetDetail("Earth", cm.rgb(40, 130, 240), cm.rgb(20, 60, 120), cm.rgb(100, 200, 255), false, 2, Array("? ISRO Headquarters: SDSC SHAR, Sriharikota", "? Main Launch Vehicles: Next-Gen LVM3 and PSLV", "? Advanced Indigenous GSLV CE-20 Cryogenic Engine", "? NISAR Radar: NASA & ISRO Joint Mega Project", "? Geostationary Transfer Orbit (GTO) Precision", "? Advanced Telemetry & Tracking Networks"), "Which propellants are used in ISRO's indigenous CE-20 cryogenic engine?", Array("UDMH + N2O4", "LOX + LH2", "RP-1 + LOX", "MMH + MON3"), 1),
  PlanetDetail("Moon", cm.rgb(180, 180, 180), cm.rgb(90, 90, 90), cm.rgb(230, 230, 230), false, 2, Array("? Chandrayaan-3 Historic South Pole Success", "? Precision Autonomous Landing: 69.37� South", "? Advanced Science Payloads: ChaSTE, ILSA, RAMBHA", "? Pragyan Rover APXS & LIBS AI Instruments", "? Trans-Lunar Injection (TLI) Trajectory Mapping", "? Lunar Soil Advanced Thermal Analysis"), "Which payload on the Pragyan Rover performs laser-induced spectroscopy?", Array("ChaSTE", "APXS", "LIBS", "SHAPE"), 2),
  PlanetDetail("Mars", cm.rgb(200, 70, 40), cm.rgb(100, 30, 15), cm.rgb(255, 130, 100), false, 2, Array("? Mars Orbiter Mission (MOM) - Mangalyaan", "? Launch Vehicle: PSLV-XL C25 Advanced Config", "? Interplanetary Hohmann Transfer Optimization", "? MENCA Exosphere Advanced Analyzer", "? Neutral Lyman-Alpha Photometer (LAP)", "? Methane Sensor for Mars (MSM Payload)"), "Which transfer orbit path was utilized for the Mars Orbiter Mission?", Array("Bi-elliptic transfer", "Trans-Mars Injection (TMI)", "Direct hyperbolic drag", "Aerocapture drag"), 1),
  PlanetDetail("Jupiter", cm.rgb(210, 140, 90), cm.rgb(100, 60, 40), cm.rgb(255, 190, 140), true, 2, Array("? Deep Space Gas Giant Exploration", "? Gravity: 24.79 m/s� | Powerful Radiation Belts", "? Subsurface Water Ocean Analysis on Europa", "? Internal Tidal Heating Advanced Mechanism", "? Galilean Moons Laplace Resonance Orbit", "? Massive Gas Giant Composition Matrix"), "What generates the internal heating within Jupiter's moon Europa?", Array("Nuclear fission", "Tidal flexing", "Solar radiation", "Atmospheric friction"), 1),
  PlanetDetail("Saturn", cm.rgb(190, 170, 110), cm.rgb(90, 80, 50), cm.rgb(240, 230, 160), true, 2, Array("? Advanced Ring System Dynamics", "? Gravity: 10.44 m/s� | Titan Hydrocarbon Mapping", "? Active Cryovolcanism Tracking on Enceladus", "? Gravitational Ring Shepherd Moons Telemetry", "? North Pole Hexagonal Jet Stream Analysis", "? Cassini-Huygens Advanced Mission Data"), "What is the primary reason Saturn's rings remain stable?", Array("Strong magnetic field", "Shepherd moons gravitational containment", "Solar wind pressure", "Centrifugal repulsion"), 1),
  PlanetDetail("Uranus", cm.rgb(100, 200, 220), cm.rgb(40, 90, 100), cm.rgb(180, 240, 255), true, 2, Array("? Ice Giant Advanced Exploration", "? Gravity: 8.69 m/s� | Extreme 97.77� Axial Tilt", "? Methane Mantle Overlay Spectroscopy", "? Off-center Offset Magnetic Axis Calculation", "? Retrograde Rotation Advanced Profile", "? Outer Solar System Transition Boundary"), "What is unique about Uranus's magnetic axis?", Array("Aligned straight with spin axis", "Tilted 59 degrees from spin axis and offset from center", "Zero magnetic field", "Constantly fluctuating"), 1),
  PlanetDetail("Neptune", cm.rgb(50, 90, 220), cm.rgb(20, 40, 100), cm.rgb(130, 170, 255), true, 2, Array("? Outermost Frontier Planetary Mission", "? Gravity: 11.15 m/s� | Supersonic Winds (2,100 km/h)", "? Retrograde Orbit of Triton Moon Tracking", "? Active Nitrogen Geyser Plumes Telemetry", "? Advanced Energy Radiation Matrix", "? Kuiper Belt Threshold Boundary"), "Why does Neptune radiate 2.6 times more energy than it receives from the Sun?", Array("Internal primordial core cooling", "Nuclear fusion core", "Solar wind absorption", "Atmospheric lightning"), 0)
)

val keplerSolarSystemMap = Array(
  PlanetDetail("Kepler-Sun", cm.rgb(255, 220, 50), cm.rgb(150, 100, 10), cm.rgb(255, 255, 150), false, 2, Array("? Advanced Exoplanet Host Star", "? Kepler-22 System Center", "? Stable Orange-Colored Star Matrix", "? K-type Orange Dwarf Advanced Classification", "? Long-Lived Main-Sequence Star Telemetry", "? Spectral Class: K2V Advanced Star"), "What spectral class is the host star of Kepler systems?", Array("G-type main sequence", "K-type orange dwarf", "M-type red dwarf", "White dwarf"), 1),
  PlanetDetail("Kepler-22b", cm.rgb(70, 180, 150), cm.rgb(30, 90, 70), cm.rgb(120, 240, 200), false, 2, Array("? First Habitable 'Super-Earth' Discovery", "? Radius: ~2.4x Earth Size", "? Orbital Distance: 0.85 AU Precision", "? Advanced Climate Modeling Target", "? Exoplanet Atmospheric Composition Study"), "What method was used to discover the exoplanet Kepler-22b?", Array("Radial velocity", "Transit photometry method", "Gravitational lensing", "Direct imaging"), 1),
  PlanetDetail("Kepler-16b", cm.rgb(200, 160, 220), cm.rgb(90, 70, 110), cm.rgb(245, 210, 255), true, 2, Array("? Famous 'Tatooine' Dual-Star System", "? Orbits Two Stars Simultaneously", "? Gas Giant Composition (Saturn-sized)", "? Precise Eclipse Timing Variations", "? Advanced Orbital Mechanics Analysis"), "Why is the Kepler-16b system scientifically unique?", Array("It orbits two stars simultaneously", "It has liquid water oceans", "Its orbit is completely retrograde", "It is larger than Jupiter"), 0),
  PlanetDetail("Kepler-186f", cm.rgb(140, 210, 110), cm.rgb(60, 90, 45), cm.rgb(200, 255, 170), false, 2, Array("? First Earth-Sized Planet in Habitable Zone", "? Potential Liquid Water Surface Indicator", "? High Probability Rocky Surface Matrix", "? Distance from Earth: ~580 Light-Years", "? Astrobiological Target Analysis"), "What is the main significance of exoplanet Kepler-186f?", Array("First earth-sized planet found in star's habitable zone", "First planet discovered with rings", "Closest planet to Earth", "Massive gas giant"), 0),
  PlanetDetail("Kepler-452b", cm.rgb(90, 140, 200), cm.rgb(40, 70, 110), cm.rgb(160, 210, 255), false, 2, Array("? Officially Designated 'Earth's Cousin'", "? Orbital Year: 385 Days Precision", "? Super-Earth Mass (~5 Earth Masses)", "? Host Star: G-type Solar Twin Tracking", "? Advanced Deep Space Survey Target"), "What type of star does Kepler-452b orbit around?", Array("Our Sun (Solar Twin)", "Alpha Centauri A", "Proxima Centauri", "Sirius"), 0),
  PlanetDetail("Kepler-10b", cm.rgb(220, 90, 90), cm.rgb(110, 40, 40), cm.rgb(255, 160, 160), false, 2, Array("? Extreme 'Lava World' Molten Surface", "? Ultra-Close Stellar Proximity (>1,300�C)", "? Distance from Earth: ~560 Light-Years", "? Thermal Radiation Mapping", "? High-Temperature Material Analysis"), "What defines the intense environment of Kepler-10b?", Array("Warm icy world", "Extreme proximity to star causing molten lava surface", "Thick methane ocean", "Deep liquid water layer"), 1),
  PlanetDetail("Kepler-62f", cm.rgb(80, 190, 210), cm.rgb(35, 90, 100), cm.rgb(150, 245, 255), false, 2, Array("? Prime Ocean World Candidate", "? Size: ~40% Larger than Earth", "? Host Star: K-type Orange Dwarf System", "? Distance from Earth: ~1,200 Light-Years", "? Hydro-Geological Survey Target"), "How does Kepler-62f's size compare to Earth?", Array("Half the size of Earth", "About 40% larger than Earth", "Ten times larger", "Exact identical size"), 1),
  PlanetDetail("Kepler-90i", cm.rgb(230, 150, 60), cm.rgb(110, 70, 20), cm.rgb(255, 210, 130), false, 2, Array("? Part of 8-Planet Solar System Architecture", "? Discovered Using Advanced Google AI Machine Learning", "? Neural Network Deep Data Processing", "? Multi-Planet Orbital Resonance Matrix", "? Next-Gen Computational Astronomy"), "Which technical advancement helped discover Kepler-90i?", Array("Google AI machine learning neural networks", "Manual human telescope sighting", "Radio wave audio decoding", "Mars rover telemetry"), 0),
  PlanetDetail("Kepler-442b", cm.rgb(100, 220, 160), cm.rgb(45, 100, 75), cm.rgb(180, 255, 220), false, 2, Array("? Highly Habitable Rocky World Target", "? Optimal Stellar Illumination Profile", "? Advanced Stellar Radiation Flux Mapping", "? High Likelihood of Rocky Terrestrial Crust", "? Astrobiological Index: Premium Tier"), "Why is Kepler-442b ranked high in habitability lists?", Array("Optimal stellar radiation and rocky scale", "Extreme proximity to Jupiter", "Rapid rotational speed", "Complete lack of atmosphere"), 0),
  PlanetDetail("K2-18b", cm.rgb(60, 200, 180), cm.rgb(20, 90, 80), cm.rgb(140, 255, 235), false, 2, Array("? 'Hycean' Hydrogen-Rich Water Planet", "? Water Vapor & Organic Molecules Detected", "? Subsurface Liquid Ocean Under Atmosphere", "? Located in Leo Constellation Telemetry", "? Advanced Spectroscopy Target"), "What unique atmospheric molecules were detected on K2-18b by telescopes?", Array("Water vapor and carbon-bearing molecules", "Neon and helium only", "Pure ammonia", "Sulfuric acid"), 0)
)

val starCount = 200
val starX = Array.fill(starCount)(randomDouble(0, cwidth))
val starY = Array.fill(starCount)(randomDouble(0, cheight))
val starSize = Array.fill(starCount)(randomDouble(1.0, 3.0))

var waveAngle = 0.0; var chakraRotation = 0.0; var neonGlowPhase = 0.0; var globalTime = 0.0; var currentSolarSystemId = 1 

def getActivePlanetList() = if (currentSolarSystemId == 1) Array("Sun", "Mercury", "Venus", "Earth", "Moon", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune") else Array("Kepler-Sun", "Kepler-22b", "Kepler-16b", "Kepler-186f", "Kepler-452b", "Kepler-10b", "Kepler-62f", "Kepler-90i", "Kepler-442b", "K2-18b")
def getActivePlanetDetailsMap() = if (currentSolarSystemId == 1) realSolarSystemMap else keplerSolarSystemMap

var selectedPlanet = "Jupiter"; var planetLocked = false; var customAlertMessage = ""; var alertTimer = 0.0
var isTimerRunning = false; var countdownTimer = 10.0; var isSpaceTravelling = false; var spaceTravelProgress = 0.0
var isLandingOnPlanet = false; var landingProgress = 0.0; var isLaunched = false; var isLanded = false
var rocketCurrentX = 90.0; var rocketCurrentY = cheight - 170.0; var doorOpeningProgress = 0.0
var astronautOut = false; var astroWaitTimer = 0.0; var infoPanelShown = false; var infoPageNumber = 1
var astroWalkToPlantX = 0.0; var isFlagPlantedOnPlanet = false; var flagPlantProgress = 0.0
val plantedFlagX = (cwidth / 2.0) - 80.0; val plantedFlagY = 155.0
var isAstronautReturningIn = false; var quizActive = false; var quizFeedback = ""; var isMiniGameActive = false
var readyToReturnEarth = false; var landingLegProgress = 0.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 * 12.0
  exhaustRibbons.append(TricolorRibbonNode(x - 8 + math.sin(t) * 6, 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 + 8 + math.cos(t) * 6, y, 1.0, cm.rgb(18, 136, 7), t + 4.0))
}

def updateExhaust() {
  exhaustRibbons.filterInPlace(_.life > 0)
  repeatFor(exhaustRibbons) { p => p.y -= 4.5; p.x += math.sin(globalTime * 10.0 + p.waveOffset) * 2.5; p.life -= 0.05 }
}

var miniGameTimer = 15.0; var isMiniGameTimerRunning = false
var devilPlayerX = (cwidth / 2.0) - 180.0; var devilPlayerY = 130.0; var devilPlayerVy = 0.0; var devilPlayerVx = 0.0
var isGrounded = false; var canDoubleJump = false; var jumpKeyPressedLastFrame = false
var trollKeyX = (cwidth / 2.0) + 140.0; var trollKeyY = 140.0; var isDevilKeyCollected = false; var exitDoorX = (cwidth / 2.0) - 180.0
var activeGameMode = 2

var isReturnTimerRunning = false; var returnCountdownTimer = 5.0; var isReturnLaunched = false
var isLandingOnEarth = false; var earthLandingProgress = 0.0; var isLandedOnEarth = false
var earthAstronautWalkRightProgress = 0.0; var isParadeSceneActive = false
var astroParadeWalkX = -50.0; var armyParadeWalkX = cwidth + 50.0; var isParadeInPosition = false

def dieAndResetDevilLevel(msg: String) {
  isGameAudioAllowed = true; playSoundFx(38, 300); customAlertMessage = s"?? $msg"; alertTimer = 1.8; miniGameTimer = 15.0; isMiniGameTimerRunning = true
  repeatFor(getActivePlanetDetailsMap()) { pd => if (pd.name == selectedPlanet) activeGameMode = pd.gameModeType }
  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.2; if (!anthemFinished) playJanaGanaStep(); return }
  waveAngle += 0.2; chakraRotation += 0.2; neonGlowPhase += 0.2; globalTime += 0.025; updateExhaust()
  if (!isMiniGameActive) isGameAudioAllowed = false
  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 = cwidth / 2.0; var targetY = cheight / 2.0; val pList = getActivePlanetList()
    for (i <- pList.indices) if (pList(i) == selectedPlanet) { val a = globalTime * (0.2 + i * 0.03); targetX = cwidth / 2.0 - 30.0 + math.cos(a) * ((i + 1) * 16.0); targetY = cheight / 2.0 + math.sin(a) * ((i + 1) * 10.0) }
    val curX = 90.0 + (targetX - 90.0) * spaceTravelProgress; val curY = (cheight - 170.0) + (targetY - (cheight - 170.0)) * spaceTravelProgress; val arc = math.sin(spaceTravelProgress * math.Pi) * 90.0
    rocketCurrentX = curX + arc; rocketCurrentY = curY - arc
    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; isGameAudioAllowed = true; 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 += 0.8
      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.2
    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) { isReturnTimerRunning = false; isReturnLaunched = true } }
  if (isReturnLaunched && !isLandingOnEarth && !isLandedOnEarth) { 
    addTricolorExhaust(rocketCurrentX, rocketCurrentY - 20); rocketCurrentY += 4.5
    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; isGameAudioAllowed = true; playSoundFx(40, 250) }
  }

  if (isLandedOnEarth && !isParadeSceneActive) { earthAstronautWalkRightProgress += 2.5; if (earthAstronautWalkRightProgress > cwidth / 2.0 + 200.0) isParadeSceneActive = true }
  if (isParadeSceneActive && !isParadeInPosition) {
    if (astroParadeWalkX < cwidth / 2.0 - 120.0) astroParadeWalkX += 1.5
    if (armyParadeWalkX > cwidth / 2.0 + 120.0) armyParadeWalkX -= 1.5
    if (astroParadeWalkX >= cwidth / 2.0 - 120.0 && armyParadeWalkX <= cwidth / 2.0 + 120.0) { isParadeInPosition = true; startAnthemPhase = true }
  }

  if (isMiniGameActive) {
    isGameAudioAllowed = true; val gx = cwidth / 2.0 - 220.0; val gy = cheight / 2.0 - 100.0
    if (isMiniGameTimerRunning) { miniGameTimer -= 0.04; if (miniGameTimer <= 0.0) dieAndResetDevilLevel("Time Out! Mission Failed!") }

    val floorY = gy + 170.0
    if (isKeyPressed(Kc.VK_RIGHT) && devilPlayerX < gx + 410) devilPlayerX += 5.2
    if (isKeyPressed(Kc.VK_LEFT) && devilPlayerX > gx + 15) devilPlayerX -= 5.2
    val upPressedNow = isKeyPressed(Kc.VK_UP)
    if (upPressedNow && !jumpKeyPressedLastFrame) {
      if (isGrounded) { devilPlayerVy = -10.5; isGrounded = false; canDoubleJump = true; playSoundFx(60, 50) }
      else if (canDoubleJump) { devilPlayerVy = -9.4; 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 = "? Advanced ISRO Rover Complete!"; alertTimer = 3.5
    }
  }
}

def drawTricolorExhaustRibbons(canvas: CanvasDraw) {
  repeatFor(exhaustRibbons) { p => canvas.fill(p.col.getRed, p.col.getGreen, p.col.getBlue, (p.life * 230).toInt); canvas.noStroke(); canvas.ellipse(p.x, p.y, p.life * 12.0, p.life * 6.0) }
}

def drawFullSolarSystem(canvas: CanvasDraw) {
  val cx = cwidth / 2.0 - 20.0; val cy = cheight / 2.0 - 10.0
  canvas.noFill(); val pList = getActivePlanetList()
  for (i <- pList.indices) { canvas.stroke(0, 190, 230, 100); canvas.strokeWeight(1.8); canvas.ellipse(cx, cy, (i * 18.0 + 30.0) * 2, (i * 11.0 + 18.0) * 2) }
  canvas.fill(255, 230, 0); canvas.stroke(255, 120, 0); canvas.strokeWeight(8.0); canvas.ellipse(cx, cy, 60, 60)

  for (i <- pList.indices) {
    val pName = pList(i)
    if (pName != "Sun" && pName != "Kepler-Sun") {
      val angle = globalTime * (0.2 + i * 0.03); val curX = cx + math.cos(angle) * (i * 18.0 + 30.0); val curY = cy + math.sin(angle) * (i * 11.0 + 18.0)
      var pCol = cm.rgb(200, 200, 200); var pRing = false
      repeatFor(getActivePlanetDetailsMap()) { pd => if (pd.name == pName) { pCol = pd.surfaceCol; pRing = pd.hasRings } }
      if (pRing) { canvas.noFill(); canvas.stroke(240, 210, 160, 220); canvas.strokeWeight(3.0); canvas.ellipse(curX, curY, 32, 13) }
      canvas.fill(pCol); canvas.stroke(255, 255, 255); canvas.strokeWeight(1.5); canvas.ellipse(curX, curY, 14, 14)
      if (!planetLocked && isMousePressed && math.abs(mouseX - curX) < 20 && math.abs(mouseY - curY) < 20) {
        if (pName == "Earth") { selectedPlanet = "Earth"; customAlertMessage = "Already on Earth!"; alertTimer = 3.0 } else selectedPlanet = pName
      }
      if (pName == selectedPlanet) { canvas.noFill(); canvas.stroke(0, 255, 255); canvas.strokeWeight(3.0); canvas.ellipse(curX, curY, 28, 28) }
    }
  }
}

def drawPlanetList(canvas: CanvasDraw) {
  canvas.fill(15, 20, 40, 240); canvas.stroke(0, 255, 255); canvas.strokeWeight(2.5); canvas.rect(10, 10, 195, 410)
  canvas.fill(255, 255, 255); canvas.text("ISRO Mission Map", 15, 30)
  canvas.fill(0, 120, 200); canvas.stroke(255, 255, 255); canvas.strokeWeight(1.5); canvas.rect(15, 40, 185, 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 <= 200 && mouseY >= 40 && mouseY <= 68) {
    currentSolarSystemId = if (currentSolarSystemId == 1) 2 else 1; selectedPlanet = if (currentSolarSystemId == 1) "Earth" else "Kepler-22b"
  }
  val pList = getActivePlanetList()
  for (i <- pList.indices) {
    val py = 88.0 + (i * 26.0)
    if (!planetLocked && isMousePressed && mouseX >= 15 && mouseX <= 200 && mouseY >= py - 11 && mouseY <= py + 10) selectedPlanet = pList(i)
    if (pList(i) == selectedPlanet) { canvas.fill(0, 160, 60); canvas.rect(15, py - 11, 185, 22); canvas.fill(255, 255, 255) } else canvas.fill(200, 200, 200)
    canvas.text(s"? ${pList(i)}", 20, py)
  }
}

def draw3DPlanetPreview(canvas: CanvasDraw) {
  val boxX = cwidth - 250.0; val boxY = 15.0; canvas.fill(15, 20, 40, 240); canvas.stroke(0, 255, 255); canvas.strokeWeight(2.0); canvas.rect(boxX, boxY, 235, 225)
  canvas.fill(255, 255, 255); canvas.text(s"Advanced 3D: $selectedPlanet", boxX + 12, boxY + 22)
  var pCol = cm.rgb(200, 70, 40); var pAccent = cm.rgb(255, 130, 100); var pRings = false
  repeatFor(getActivePlanetDetailsMap()) { pd => if (pd.name == selectedPlanet) { pCol = pd.surfaceCol; pAccent = pd.accent3D; pRings = pd.hasRings } }
  val cx = boxX + 117.5; val cy = boxY + 127.5
  if (pRings) { canvas.noFill(); canvas.stroke(210, 200, 170, 220); canvas.strokeWeight(7.0); canvas.ellipse(cx, cy, 180, 52) }
  canvas.fill(pCol); canvas.stroke(pAccent); canvas.strokeWeight(3.0); canvas.ellipse(cx, cy, 115, 115)
}

def drawWavingTricolorFlagWithAshokChakra(canvas: CanvasDraw, fx: Double, fy: Double) {
  canvas.stroke(220, 220, 220); canvas.strokeWeight(3); canvas.line(fx, fy + 45, fx, fy - 10)
  var x = 0.0; while (x < 50.0) {
    val yOffset = math.sin(waveAngle + (x * 0.12)) * 4.0; canvas.strokeWeight(2.5)
    canvas.stroke(255, 153, 51); canvas.line(fx + x, fy + 20 + yOffset, fx + x, fy + 30 + yOffset)
    canvas.stroke(255, 255, 255); canvas.line(fx + x, fy + 10 + yOffset, fx + x, fy + 20 + yOffset)
    canvas.stroke(18, 136, 7); canvas.line(fx + x, fy + yOffset, fx + x, fy + 10 + yOffset); x += 2.0
  }
  canvas.fill(0, 0, 180); canvas.noStroke(); canvas.ellipse(fx + 25.0, fy + 15.0 + math.sin(waveAngle + (25.0 * 0.12)) * 4.0, 8, 8)
}

def drawPlanetSurfaceBackground(canvas: CanvasDraw) {
  var surfCol = cm.rgb(100, 30, 15); var darkSurfCol = 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); canvas.fill(darkSurfCol); canvas.rect(0, 120, cwidth, 25)
  if (isFlagPlantedOnPlanet) drawWavingTricolorFlagWithAshokChakra(canvas, plantedFlagX, plantedFlagY)
}

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 * 9) * 5.0 
  canvas.stroke(if (isArmy) cm.rgb(30, 60, 20) else cm.rgb(180, 180, 200)); canvas.strokeWeight(5)
  canvas.line(-5, 0, -6 + stepSwing, -22); canvas.line(5, 0, 6 - stepSwing, -22)
  canvas.fill(if (isArmy) cm.rgb(75, 105, 47) else cm.rgb(240, 240, 250)); canvas.stroke(0, 255, 255); canvas.strokeWeight(1.5); canvas.rect(-10, 0, 20, 32)
  canvas.fill(if (isArmy) cm.rgb(210, 160, 120) else cm.rgb(255, 255, 255)); canvas.ellipse(0, 42, 18, 18)
  canvas.popMatrix()
}

def drawParadeGroundScene(canvas: CanvasDraw) {
  canvas.fill(34, 139, 34); canvas.noStroke(); canvas.rect(0, 0, cwidth, 140); canvas.fill(25, 90, 25); canvas.rect(0, 125, cwidth, 25)
  val fx = cwidth / 2.0 - 70.0; val fy = cheight / 2.0 + 10.0; canvas.stroke(220, 220, 220); canvas.strokeWeight(6); canvas.line(fx, fy + 78, fx, fy - 140)
  var x = 0.0; while (x < 140.0) {
    val yOffset = math.sin(waveAngle + (x * 0.05)) * 8.0; canvas.strokeWeight(5.0)
    canvas.stroke(255, 153, 51); canvas.line(fx + x, fy + 52 + yOffset, fx + x, fy + 78 + yOffset)
    canvas.stroke(255, 255, 255); canvas.line(fx + x, fy + 26 + yOffset, fx + x, fy + 52 + yOffset)
    canvas.stroke(18, 136, 7); canvas.line(fx + x, fy + yOffset, fx + x, fy + 26 + yOffset); x += 4.0
  }
  canvas.fill(0, 0, 180); canvas.noStroke(); canvas.ellipse(fx + 70.0, fy + 30.0 + math.sin(waveAngle + 3.5) * 8.0, 18, 18)
  for (i <- 0 until 3) drawPersonCharacter(canvas, astroParadeWalkX - (i * 35.0), 165.0, false, isParadeInPosition)
  for (i <- 0 until 3) drawPersonCharacter(canvas, armyParadeWalkX + (i * 35.0), 165.0, true, isParadeInPosition)
  if (charIndex > 0) {
    val lines = fullAnthemText.substring(0, charIndex).split("\n"); var startY = cheight - 20.0
    for (l <- lines) { canvas.fill(255, 215, 0, 100); canvas.text(l, 21.0, startY - 1); canvas.fill(255, 255, 255); canvas.text(l, 20.0, startY); startY -= 15.0 }
  }
}

def drawEarthFirstLandingScene(canvas: CanvasDraw) {
  canvas.fill(34, 139, 34); canvas.noStroke(); canvas.rect(0, 0, cwidth, 140); canvas.fill(30, 100, 200); 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 = cwidth - 250.0; val btnY = 250.0
    if (selectedPlanet != "Sun" && selectedPlanet != "Kepler-Sun" && !isTimerRunning && !quizActive) {
      canvas.fill(255, 80, 0); canvas.stroke(255, 220, 0); canvas.strokeWeight(3.5); canvas.rect(btnX, btnY, 235, 45)
      canvas.fill(255, 255, 255); canvas.text("? Advanced ISRO Launch", btnX + 20, 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, 150); canvas.strokeWeight(4.5); 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 ADVANCED", -35, 48) }
  canvas.fill(245, 245, 250); canvas.stroke(0, 255, 255); canvas.strokeWeight(2.5); canvas.rect(-12, -45, 24, 45)
  canvas.fill(255, 60, 60); canvas.stroke(255, 200, 200); canvas.strokeWeight(2.0); canvas.beginShape(); canvas.vertex(0, 25); canvas.vertex(-12, 0); canvas.vertex(12, 0); canvas.endShape()
  canvas.stroke(200, 200, 200); canvas.strokeWeight(3.5)
  canvas.line(-12, -40, -12 - (landingLegProgress * 15), -60); canvas.line(12, -40, 12 + (landingLegProgress * 15), -60)
  if (isLanded && !isParadeSceneActive) {
    canvas.fill(40, 40, 50); 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)
      canvas.fill(240, 240, 250); canvas.stroke(0, 255, 255); canvas.strokeWeight(1.5); canvas.rect(-7, -10, 14, 20)
      canvas.fill(255, 255, 255); canvas.ellipse(0, 14, 14, 14); canvas.fill(0, 180, 240); canvas.ellipse(0, 14, 9, 7)
      canvas.popMatrix()
    }
  }
  canvas.popMatrix()
}

def drawQuizPopup(canvas: CanvasDraw) {
  if (quizActive) {
    val qx = cwidth / 2.0 - 225.0; val qy = cheight / 2.0 - 130.0
    canvas.fill(15, 20, 45, 245); canvas.stroke(255, 215, 0); canvas.strokeWeight(3.0); canvas.rect(qx, qy, 450, 260)
    canvas.fill(255, 255, 255); canvas.text(s"Advanced 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.qText; opts = pd.qOpts; corr = pd.correctOpt } }
    canvas.fill(255, 220, 100); canvas.text(qText, qx + 15, qy + 52)
    for (i <- opts.indices) {
      val optY = qy + 75.0 + (i * 32.0); canvas.fill(30, 40, 80); 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! Telemetry Verified!"; alertTimer = 3.0 }
        else quizFeedback = "Incorrect! Try Again."
      }
    }
    if (quizFeedback != "") { canvas.fill(255, 50, 50); canvas.text(quizFeedback, qx + 20, qy + 235) }
  }
}

def drawPlanetInfoPopup(canvas: CanvasDraw) {
  if (infoPanelShown) {
    val ix = cwidth / 2.0 - 230.0; val iy = cheight / 2.0 - 130.0
    canvas.fill(15, 20, 45, 245); canvas.stroke(0, 255, 255); canvas.strokeWeight(3.0); canvas.rect(ix, iy, 460, 260)
    canvas.fill(255, 215, 0); canvas.text(s"? Advanced ISRO Info: $selectedPlanet", ix + 20, iy + 25)
    var infoLines = Array("", "", "", "", "", "")
    repeatFor(getActivePlanetDetailsMap()) { pd => if (pd.name == selectedPlanet) infoLines = pd.info }
    canvas.fill(220, 220, 240)
    val startIdx = if (infoPageNumber == 1) 0 else 3
    for (i <- 0 until 3) canvas.text(infoLines(startIdx + i), ix + 20, iy + 65.0 + (i * 30.0))
    canvas.fill(40, 100, 200); canvas.rect(ix + 20, iy + 195, 100, 35); canvas.fill(255, 255, 255); canvas.text("Next/Prev", ix + 35, iy + 218)
    if (isMousePressed && mouseX >= ix + 20 && mouseX <= ix + 120 && mouseY >= iy + 195 && mouseY <= iy + 230) infoPageNumber = if (infoPageNumber == 1) 2 else 1
    canvas.fill(0, 180, 80); canvas.rect(ix + 140, iy + 195, 150, 35); canvas.fill(255, 255, 255); canvas.text("? Rover Mission", ix + 160, iy + 218)
    if (isMousePressed && mouseX >= ix + 140 && mouseX <= ix + 290 && mouseY >= iy + 195 && mouseY <= iy + 230) { infoPanelShown = false; isMiniGameActive = true; dieAndResetDevilLevel("Rover Deployed!") }
    canvas.fill(180, 40, 40); 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(220, 30, 30, 235); canvas.stroke(255, 255, 255); canvas.strokeWeight(2.0); 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 = cwidth / 2.0 - 220.0; val gy = cheight / 2.0 - 100.0
    canvas.fill(10, 10, 25, 245); canvas.stroke(0, 255, 200); canvas.strokeWeight(3.0); canvas.rect(gx, gy, 440, 210)
    canvas.fill(255, 60, 60); canvas.text(s"?? Time: ${miniGameTimer.toInt}s", gx + 290, gy + 190)

    canvas.fill(255, 255, 255); canvas.text(s"? Advanced ISRO Rover 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, 150) else cm.rgb(100, 100, 100))
    canvas.rect(exitDoorX, gy + 135, 30, 40)
    
    // ???? strokeWeight ?? ??? ??????? ???? ??? (strokeWeight(1.5))
    canvas.fill(240, 240, 250); canvas.stroke(0, 255, 255); canvas.strokeWeight(1.5); canvas.rect(devilPlayerX - 8, devilPlayerY - 12, 16, 24)
  }
}

def viewState(canvas: CanvasDraw) {
  if (anthemFinished) {
    canvas.fill(0, 0, 0); canvas.noStroke(); canvas.rect(0, 0, cwidth, cheight)
    canvas.fill(255, 215, 0); canvas.text("?? Jai Hind! Ultimate ISRO Mission Complete ??", cwidth / 2.0 - 160.0, cheight / 2.0 + 60.0)
    canvas.fill(0, 255, 255); canvas.text("Created by Bhagyash Sahane and Dnyaneshwar Sahane", cwidth / 2.0 - 210.0, cheight / 2.0)
  } 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)); 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) } 
password()