Code Sketch


Bixuu ElementalChaosRebornEvent9
By: Mhalsakant School
Category: Programming
import java.awt.{BasicStroke, Color, Dimension, Font, GradientPaint, Graphics, Graphics2D, Polygon, RenderingHints}
import java.awt.event.{ActionEvent, ActionListener, KeyAdapter, KeyEvent, MouseAdapter, MouseEvent, WindowAdapter, WindowEvent}
import javax.swing.{JButton, JFrame, JLabel, JPanel, JTextField, SwingConstants, SwingUtilities, Timer, WindowConstants}
import scala.collection.mutable.ArrayBuffer
import scala.util.Random

object ElementalChaosRebornEvent9 {
  def main(args: Array[String]): Unit = {
    SwingUtilities.invokeLater(new Runnable {
      def run(): Unit = openWindow()
    })
  }

  def openWindow(): Unit = {
    val frame = new JFrame("INFINITY REALMS SEASON 09 - ELEMENTAL CHAOS REBORN")
    frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE)
    frame.setResizable(false)
    frame.setSize(1000, 700)
    frame.setLocationRelativeTo(null)

    var activeGame: ElementalChaosGamePanel = null
    val loginPanel = new ElementalChaosLoginPanel((name: String) => {
      activeGame = new ElementalChaosGamePanel(name)
      frame.setContentPane(activeGame)
      frame.revalidate()
      frame.repaint()
      activeGame.requestFocusInWindow()
      activeGame.startGame()
    })

    frame.addWindowListener(new WindowAdapter {
      override def windowClosing(e: WindowEvent): Unit = {
        if (activeGame != null) activeGame.stopGame()
      }
    })

    frame.setContentPane(loginPanel)
    frame.setVisible(true)
  }
}

class ElementalChaosLoginPanel(onStart: String => Unit) extends JPanel {
  setPreferredSize(new Dimension(1000, 700))
  setLayout(null)
  setBackground(new Color(10, 16, 27))

  val titleLabel = new JLabel("ELEMENTAL CHAOS REBORN", SwingConstants.CENTER)
  titleLabel.setFont(new Font("SansSerif", Font.BOLD, 38))
  titleLabel.setForeground(new Color(236, 249, 255))
  titleLabel.setBounds(130, 105, 740, 60)
  add(titleLabel)

  val seasonLabel = new JLabel("INFINITY REALMS SEASON 09  |  NATURE & ELEMENTS", SwingConstants.CENTER)
  seasonLabel.setFont(new Font("SansSerif", Font.BOLD, 17))
  seasonLabel.setForeground(new Color(139, 226, 209))
  seasonLabel.setBounds(170, 170, 660, 34)
  add(seasonLabel)

  val storyLabel = new JLabel("Restore the four elemental realms and awaken the Nature Core.", SwingConstants.CENTER)
  storyLabel.setFont(new Font("SansSerif", Font.PLAIN, 16))
  storyLabel.setForeground(new Color(208, 225, 233))
  storyLabel.setBounds(160, 230, 680, 34)
  add(storyLabel)

  val nameLabel = new JLabel("ENTER YOUR EXPLORER NAME", SwingConstants.CENTER)
  nameLabel.setFont(new Font("SansSerif", Font.BOLD, 15))
  nameLabel.setForeground(new Color(229, 244, 247))
  nameLabel.setBounds(330, 325, 340, 28)
  add(nameLabel)

  val nameField = new JTextField("Explorer")
  nameField.setFont(new Font("SansSerif", Font.PLAIN, 20))
  nameField.setHorizontalAlignment(SwingConstants.CENTER)
  nameField.setBounds(350, 360, 300, 42)
  add(nameField)

  val startButton = new JButton("ENTER THE ELEMENTAL REALMS")
  startButton.setFont(new Font("SansSerif", Font.BOLD, 15))
  startButton.setForeground(Color.WHITE)
  startButton.setBackground(new Color(25, 115, 105))
  startButton.setFocusPainted(false)
  startButton.setBounds(325, 425, 350, 48)
  startButton.addActionListener(new ActionListener {
    def actionPerformed(e: ActionEvent): Unit = {
      var chosenName = nameField.getText.trim
      if (chosenName.length == 0) chosenName = "Explorer"
      onStart(chosenName)
    }
  })
  add(startButton)

  val controlsLabel = new JLabel("WASD / ARROWS: MOVE     SPACE: DASH     1-4: SELECT ELEMENT     F: CAST POWER", SwingConstants.CENTER)
  controlsLabel.setFont(new Font("SansSerif", Font.PLAIN, 12))
  controlsLabel.setForeground(new Color(164, 190, 197))
  controlsLabel.setBounds(80, 590, 840, 24)
  add(controlsLabel)

  val safetyLabel = new JLabel("Offline single-player adventure  |  Progress is kept only for this game session", SwingConstants.CENTER)
  safetyLabel.setFont(new Font("SansSerif", Font.PLAIN, 12))
  safetyLabel.setForeground(new Color(126, 153, 161))
  safetyLabel.setBounds(180, 620, 640, 22)
  add(safetyLabel)

  override def paintComponent(g: Graphics): Unit = {
    super.paintComponent(g)
    val g2 = g.asInstanceOf[Graphics2D]
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON)
    g2.setPaint(new GradientPaint(0, 0, new Color(8, 20, 32), 0, getHeight, new Color(24, 62, 58)))
    g2.fillRect(0, 0, getWidth, getHeight)

    var i = 0
    while (i < 75) {
      val x = (i * 137 + 29) % getWidth
      val y = (i * 79 + 17) % getHeight
      val radius = 2 + (i % 4)
      val colors = Array(new Color(106, 242, 207, 95), new Color(255, 180, 95, 90), new Color(125, 178, 255, 95), new Color(194, 145, 255, 90))
      g2.setColor(colors(i % colors.length))
      g2.fillOval(x, y, radius, radius)
      i += 1
    }

    g2.setColor(new Color(42, 154, 120, 55))
    g2.fillOval(345, 20, 310, 270)
    g2.setColor(new Color(8, 27, 34, 130))
    g2.fillOval(405, 40, 260, 260)
    g2.setStroke(new BasicStroke(4.0f))
    g2.setColor(new Color(101, 235, 194, 120))
    g2.drawOval(365, 35, 270, 245)
  }
}

class ElementalChaosGamePanel(val playerName: String) extends JPanel {
  setPreferredSize(new Dimension(1000, 700))
  setBackground(new Color(13, 25, 32))
  setFocusable(true)

  class ElementShard(var x: Double, var y: Double, val element: Int, var collected: Boolean)
  class ChaosWisp(var x: Double, var y: Double, var stunnedTicks: Int)

  val realmNames = Array("EMBERROOT WILDS", "TIDAL HEART LAGOON", "STONEVEIL HIGHLANDS", "SKYBLOOM SANCTUARY")
  val realmHints = Array(
    "Collect Fire Seeds and restore the Emberroot Flame.",
    "Gather Water Pearls and calm the Tidal Heart.",
    "Find Earth Cores and repair the Stoneveil Pillar.",
    "Collect Wind Feathers and awaken the Nature Core."
  )
  val realmTopColors = Array(
    new Color(93, 42, 29),
    new Color(17, 63, 87),
    new Color(51, 75, 47),
    new Color(42, 52, 92)
  )
  val realmBottomColors = Array(
    new Color(34, 24, 24),
    new Color(12, 35, 57),
    new Color(28, 45, 31),
    new Color(23, 30, 57)
  )
  val elementNames = Array("FIRE", "WATER", "EARTH", "WIND")
  val elementColors = Array(
    new Color(255, 116, 65),
    new Color(83, 197, 245),
    new Color(150, 206, 112),
    new Color(200, 222, 255)
  )

  val pressedKeys = scala.collection.mutable.Set[Int]()
  val random = new Random()
  val shards = ArrayBuffer[ElementShard]()
  val wisps = ArrayBuffer[ChaosWisp]()

  var realmIndex = 0
  var playerX = 95.0
  var playerY = 350.0
  var playerHealth = 5
  var score = 0
  var energy = 60
  var totalShards = 0
  var selectedElement = 0
  var shieldTicks = 0
  var dashTicks = 0
  var dashCooldown = 0
  var castCooldown = 0
  var invulnerableTicks = 0
  var tickCount = 0
  var paused = false
  var gameOver = false
  var victory = false
  var bossActive = false
  var bossHealth = 6
  var bossStunTicks = 0
  var bossX = 820.0
  var bossY = 350.0
  var message = "Collect 4 elemental shards, then reach the gate on the right."
  var mouseTargetX = -1.0
  var mouseTargetY = -1.0
  var gameTimer: Timer = null

  loadRealm()

  def startGame(): Unit = {
    if (gameTimer == null) {
      gameTimer = new Timer(25, new ActionListener {
        def actionPerformed(e: ActionEvent): Unit = updateGame()
      })
      gameTimer.start()
    }
    requestFocusInWindow()
  }

  def stopGame(): Unit = {
    if (gameTimer != null) gameTimer.stop()
  }

  def currentShardCount(): Int = shards.count(s => s.collected)

  def distance(ax: Double, ay: Double, bx: Double, by: Double): Double = {
    val dx = ax - bx
    val dy = ay - by
    Math.sqrt(dx * dx + dy * dy)
  }

  def limit(value: Double, low: Double, high: Double): Double = Math.max(low, Math.min(high, value))

  def loadRealm(): Unit = {
    playerX = 92.0
    playerY = 360.0
    mouseTargetX = -1.0
    mouseTargetY = -1.0
    shards.clear()
    val shardElement = realmIndex
    shards += new ElementShard(235.0, 190.0, shardElement, false)
    shards += new ElementShard(405.0, 510.0, shardElement, false)
    shards += new ElementShard(590.0, 210.0, shardElement, false)
    shards += new ElementShard(760.0, 490.0, shardElement, false)
    wisps.clear()
    wisps += new ChaosWisp(390.0, 345.0, 0)
    wisps += new ChaosWisp(670.0, 400.0, 0)
    if (realmIndex >= 2) wisps += new ChaosWisp(520.0, 530.0, 0)
    bossActive = (realmIndex == 3)
    bossHealth = 6
    bossStunTicks = 0
    bossX = 835.0
    bossY = 350.0
    shieldTicks = 0
    dashTicks = 0
    invulnerableTicks = 70
    message = realmHints(realmIndex)
  }

  def selectElement(index: Int): Unit = {
    if (index >= 0 && index < 4) {
      selectedElement = index
      message = "Selected element: " + elementNames(selectedElement) + ". Press F to cast its power."
    }
  }

  def castElementPower(): Unit = {
    if (gameOver || victory || paused || castCooldown > 0) return
    if (energy < 15) {
      message = "Not enough Nature Energy. Collect more shards!"
      return
    }
    energy -= 15
    castCooldown = 32
    var affected = 0
    if (selectedElement == 0) {
      for (w <- wisps) {
        if (distance(playerX, playerY, w.x, w.y) < 190.0) {
          w.stunnedTicks = 115
          affected += 1
        }
      }
      if (bossActive && distance(playerX, playerY, bossX, bossY) < 210.0 && bossStunTicks == 0) {
        bossHealth -= 1
        bossStunTicks = 70
        message = "EMBER BURST! The Chaos Guardian lost 1 core."
      } else {
        message = "EMBER BURST! Nearby chaos wisps are stunned."
      }
    } else if (selectedElement == 1) {
      for (w <- wisps) {
        if (distance(playerX, playerY, w.x, w.y) < 230.0) {
          w.stunnedTicks = 150
          affected += 1
        }
      }
      if (playerHealth < 5) playerHealth += 1
      if (bossActive && distance(playerX, playerY, bossX, bossY) < 230.0 && bossStunTicks == 0) {
        bossHealth -= 1
        bossStunTicks = 55
        message = "TIDAL WAVE! You healed and weakened the Guardian."
      } else {
        message = "TIDAL WAVE! Wisps are slowed and your health is restored."
      }
    } else if (selectedElement == 2) {
      shieldTicks = 150
      if (bossActive && distance(playerX, playerY, bossX, bossY) < 190.0 && bossStunTicks == 0) {
        bossHealth -= 1
        bossStunTicks = 65
        message = "EARTH SENTINEL! Shield raised and Guardian damaged."
      } else {
        message = "EARTH SENTINEL! A strong nature shield surrounds you."
      }
    } else {
      dashTicks = 35
      invulnerableTicks = Math.max(invulnerableTicks, 40)
      if (bossActive && distance(playerX, playerY, bossX, bossY) < 220.0 && bossStunTicks == 0) {
        bossHealth -= 1
        bossStunTicks = 50
        message = "GALE STRIKE! You dashed through the Guardian."
      } else {
        message = "GALE DASH! You surge forward with wind energy."
      }
    }
    if (bossHealth <= 0 && bossActive) {
      bossHealth = 0
      bossStunTicks = 9999
      message = "THE CHAOS GUARDIAN IS DEFEATED! Reach the final gate."
    }
  }

  def activateDash(): Unit = {
    if (!paused && !gameOver && !victory && dashCooldown == 0 && energy >= 8) {
      energy -= 8
      dashTicks = 24
      dashCooldown = 95
      invulnerableTicks = Math.max(invulnerableTicks, 26)
      message = "NATURE DASH!"
    }
  }

  def useShield(): Unit = {
    if (!paused && !gameOver && !victory && energy >= 12) {
      energy -= 12
      shieldTicks = 120
      message = "ELEMENTAL SHIELD ACTIVE!"
    }
  }

  def interact(): Unit = {
    if (gameOver || victory || paused) return
    if (distance(playerX, playerY, 905.0, 350.0) < 95.0) {
      if (currentShardCount() < 4) {
        message = "The gate is sealed. Collect all 4 shards first."
      } else if (realmIndex < 3) {
        realmIndex += 1
        score += 150
        energy = Math.min(100, energy + 25)
        loadRealm()
      } else if (bossHealth > 0) {
        message = "The final gate is blocked. Use elemental powers on the Chaos Guardian."
      } else {
        victory = true
        message = "THE NATURE CORE IS RESTORED! YOU SAVED THE REALMS!"
      }
    } else if (bossActive && distance(playerX, playerY, bossX, bossY) < 100.0 && bossHealth <= 0) {
      message = "The Guardian has fallen. Reach the glowing gate on the right."
    } else {
      message = "Move close to a glowing shard or the gate, then press E."
    }
  }

  def updateGame(): Unit = {
    if (paused || gameOver || victory) {
      repaint()
      return
    }

    tickCount += 1
    if (dashTicks > 0) dashTicks -= 1
    if (dashCooldown > 0) dashCooldown -= 1
    if (castCooldown > 0) castCooldown -= 1
    if (shieldTicks > 0) shieldTicks -= 1
    if (invulnerableTicks > 0) invulnerableTicks -= 1
    if (bossStunTicks > 0 && bossHealth > 0) bossStunTicks -= 1

    val baseSpeed = 2.55 + Math.min(1.25, totalShards * 0.055)
    val movementSpeed = if (dashTicks > 0) baseSpeed * 2.7 else baseSpeed
    var dx = 0.0
    var dy = 0.0

    if (pressedKeys.contains(KeyEvent.VK_A) || pressedKeys.contains(KeyEvent.VK_LEFT)) dx -= 1.0
    if (pressedKeys.contains(KeyEvent.VK_D) || pressedKeys.contains(KeyEvent.VK_RIGHT)) dx += 1.0
    if (pressedKeys.contains(KeyEvent.VK_W) || pressedKeys.contains(KeyEvent.VK_UP)) dy -= 1.0
    if (pressedKeys.contains(KeyEvent.VK_S) || pressedKeys.contains(KeyEvent.VK_DOWN)) dy += 1.0

    if (dx != 0.0 || dy != 0.0) {
      val magnitude = Math.sqrt(dx * dx + dy * dy)
      playerX += (dx / magnitude) * movementSpeed
      playerY += (dy / magnitude) * movementSpeed
      mouseTargetX = -1.0
      mouseTargetY = -1.0
    } else if (mouseTargetX >= 0.0 && mouseTargetY >= 0.0) {
      val md = distance(playerX, playerY, mouseTargetX, mouseTargetY)
      if (md < 7.0) {
        mouseTargetX = -1.0
        mouseTargetY = -1.0
      } else {
        playerX += ((mouseTargetX - playerX) / md) * movementSpeed
        playerY += ((mouseTargetY - playerY) / md) * movementSpeed
      }
    }

    playerX = limit(playerX, 35.0, 955.0)
    playerY = limit(playerY, 112.0, 635.0)

    for (s <- shards) {
      if (!s.collected && distance(playerX, playerY, s.x, s.y) < 29.0) {
        s.collected = true
        score += 50
        totalShards += 1
        energy = Math.min(100, energy + 18)
        message = elementNames(s.element) + " SHARD COLLECTED! +50 POINTS"
      }
    }

    for (w <- wisps) {
      if (w.stunnedTicks > 0) {
        w.stunnedTicks -= 1
      } else {
        val wd = distance(playerX, playerY, w.x, w.y)
        if (wd > 1.0) {
          w.x += ((playerX - w.x) / wd) * 1.05
          w.y += ((playerY - w.y) / wd) * 1.05
        }
        if (wd < 26.0 && shieldTicks == 0 && invulnerableTicks == 0) {
          playerHealth -= 1
          invulnerableTicks = 85
          w.x = 70.0 + random.nextInt(800)
          w.y = 130.0 + random.nextInt(480)
          message = "A CHAOS WISP TOUCHED YOU! Health reduced."
        }
      }
    }

    if (bossActive && bossHealth > 0) {
      if (bossStunTicks == 0) {
        val bd = distance(playerX, playerY, bossX, bossY)
        if (bd > 1.0) {
          bossX += ((playerX - bossX) / bd) * 0.72
          bossY += ((playerY - bossY) / bd) * 0.72
        }
        if (bd < 44.0 && shieldTicks == 0 && invulnerableTicks == 0) {
          playerHealth -= 1
          invulnerableTicks = 100
          message = "THE CHAOS GUARDIAN HIT YOU! Use a dash or shield."
        }
      }
    }

    if (playerHealth <= 0) {
      playerHealth = 0
      gameOver = true
      message = "YOUR ENERGY FADED. PRESS R TO TRY AGAIN."
    }
    repaint()
  }

  addKeyListener(new KeyAdapter {
    override def keyPressed(e: KeyEvent): Unit = {
      val code = e.getKeyCode
      pressedKeys += code
      if (code == KeyEvent.VK_SPACE) activateDash()
      if (code == KeyEvent.VK_F) castElementPower()
      if (code == KeyEvent.VK_Q) useShield()
      if (code == KeyEvent.VK_E) interact()
      if (code == KeyEvent.VK_1) selectElement(0)
      if (code == KeyEvent.VK_2) selectElement(1)
      if (code == KeyEvent.VK_3) selectElement(2)
      if (code == KeyEvent.VK_4) selectElement(3)
      if (code == KeyEvent.VK_P) paused = !paused
      if (code == KeyEvent.VK_R && (gameOver || victory)) restartGame()
      if (code == KeyEvent.VK_B) {
        playerX = 92.0
        playerY = 360.0
        mouseTargetX = -1.0
        mouseTargetY = -1.0
        message = "Returned to the safe starting point of this realm."
      }
      repaint()
    }
    override def keyReleased(e: KeyEvent): Unit = pressedKeys -= e.getKeyCode
  })

  addMouseListener(new MouseAdapter {
    override def mousePressed(e: MouseEvent): Unit = {
      if (e.getButton == MouseEvent.BUTTON1 && !paused && !gameOver && !victory) {
        mouseTargetX = e.getX.toDouble
        mouseTargetY = e.getY.toDouble
        requestFocusInWindow()
      }
    }
  })

  def restartGame(): Unit = {
    realmIndex = 0
    playerHealth = 5
    score = 0
    energy = 60
    totalShards = 0
    selectedElement = 0
    paused = false
    gameOver = false
    victory = false
    tickCount = 0
    loadRealm()
    message = "Your elemental journey begins again."
    requestFocusInWindow()
  }

  override def paintComponent(g: Graphics): Unit = {
    super.paintComponent(g)
    val g2 = g.asInstanceOf[Graphics2D]
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON)

    val background = new GradientPaint(0, 0, realmTopColors(realmIndex), 0, getHeight, realmBottomColors(realmIndex))
    g2.setPaint(background)
    g2.fillRect(0, 0, getWidth, getHeight)

    drawWorld(g2)
    drawShards(g2)
    drawWisps(g2)
    drawPlayer(g2)
    drawGate(g2)
    if (bossActive && bossHealth > 0) drawBoss(g2)
    drawHud(g2)

    if (paused) drawOverlay(g2, "PAUSED", "Press P to resume")
    if (gameOver) drawOverlay(g2, "REALM LOST", "Press R to restart your journey")
    if (victory) drawOverlay(g2, "NATURE CORE RESTORED!", "You completed Elemental Chaos Reborn - Press R to play again")
  }

  def drawWorld(g2: Graphics2D): Unit = {
    val shimmer = tickCount % 80
    g2.setColor(new Color(255, 255, 255, 18))
    var i = 0
    while (i < 38) {
      val px = (i * 173 + 47) % 1000
      val py = 120 + ((i * 97 + shimmer * 2) % 520)
      g2.fillOval(px, py, 3 + (i % 3), 3 + (i % 3))
      i += 1
    }

    g2.setColor(new Color(10, 20, 25, 105))
    g2.fillOval(-90, 510, 420, 190)
    g2.fillOval(260, 550, 440, 170)
    g2.fillOval(700, 520, 420, 190)

    if (realmIndex == 0) {
      g2.setColor(new Color(95, 45, 33, 220))
      g2.fillPolygon(Array(0, 190, 255, 70), Array(500, 350, 700, 700), 4)
      g2.setColor(new Color(255, 114, 58, 110))
      g2.fillOval(90, 135, 100, 100)
      g2.fillOval(755, 185, 145, 145)
      g2.setColor(new Color(57, 96, 54))
      g2.fillOval(25, 455, 125, 160)
      g2.fillOval(830, 460, 140, 170)
    } else if (realmIndex == 1) {
      g2.setColor(new Color(43, 139, 178, 110))
      g2.fillOval(120, 450, 760, 210)
      g2.setColor(new Color(130, 223, 239, 80))
      g2.fillOval(300, 480, 420, 95)
      g2.setColor(new Color(40, 111, 130))
      g2.fillOval(45, 410, 160, 170)
      g2.fillOval(790, 405, 170, 180)
    } else if (realmIndex == 2) {
      g2.setColor(new Color(92, 105, 76, 220))
      g2.fillPolygon(Array(0, 210, 350, 0), Array(480, 275, 700, 700), 4)
      g2.fillPolygon(Array(650, 870, 1000, 1000), Array(700, 310, 475, 700), 4)
      g2.setColor(new Color(159, 194, 116, 90))
      g2.fillOval(420, 450, 190, 160)
    } else {
      g2.setColor(new Color(85, 112, 153, 145))
      g2.fillOval(90, 465, 250, 145)
      g2.fillOval(650, 440, 290, 170)
      g2.setColor(new Color(192, 220, 255, 65))
      g2.fillOval(365, 170, 220, 190)
      g2.setColor(new Color(118, 172, 197, 150))
      g2.fillPolygon(Array(70, 190, 285, 115), Array(580, 400, 580, 650), 4)
    }

    g2.setColor(new Color(230, 255, 235, 34))
    g2.setStroke(new BasicStroke(2.0f))
    g2.drawLine(0, 105, 1000, 105)
    g2.drawLine(0, 650, 1000, 650)
  }

  def drawShards(g2: Graphics2D): Unit = {
    for (s <- shards if !s.collected) {
      val col = elementColors(s.element)
      val glow = 9 + (tickCount % 12)
      g2.setColor(new Color(col.getRed, col.getGreen, col.getBlue, 42))
      g2.fillOval(s.x.toInt - glow, s.y.toInt - glow, glow * 2, glow * 2)
      g2.setColor(col)
      val p = new Polygon()
      p.addPoint(s.x.toInt, s.y.toInt - 19)
      p.addPoint(s.x.toInt + 13, s.y.toInt)
      p.addPoint(s.x.toInt, s.y.toInt + 19)
      p.addPoint(s.x.toInt - 13, s.y.toInt)
      g2.fillPolygon(p)
      g2.setColor(Color.WHITE)
      g2.drawPolygon(p)
    }
  }

  def drawWisps(g2: Graphics2D): Unit = {
    for (w <- wisps) {
      if (w.stunnedTicks > 0) g2.setColor(new Color(195, 238, 255, 210))
      else g2.setColor(new Color(180, 115, 235, 205))
      g2.fillOval(w.x.toInt - 15, w.y.toInt - 18, 30, 30)
      g2.fillOval(w.x.toInt - 12, w.y.toInt - 7, 24, 20)
      g2.setColor(new Color(20, 20, 35))
      g2.fillOval(w.x.toInt - 7, w.y.toInt - 5, 4, 5)
      g2.fillOval(w.x.toInt + 3, w.y.toInt - 5, 4, 5)
    }
  }

  def drawPlayer(g2: Graphics2D): Unit = {
    val playerColor = elementColors(selectedElement)
    if (shieldTicks > 0) {
      g2.setStroke(new BasicStroke(3.0f))
      g2.setColor(new Color(140, 245, 220, 135))
      g2.drawOval(playerX.toInt - 27, playerY.toInt - 27, 54, 54)
    }
    if (dashTicks > 0) {
      g2.setColor(new Color(playerColor.getRed, playerColor.getGreen, playerColor.getBlue, 85))
      g2.fillOval(playerX.toInt - 34, playerY.toInt - 34, 68, 68)
    }
    g2.setColor(new Color(14, 24, 31))
    g2.fillOval(playerX.toInt - 12, playerY.toInt - 17, 24, 34)
    g2.setColor(playerColor)
    g2.fillOval(playerX.toInt - 9, playerY.toInt - 23, 18, 18)
    g2.setColor(Color.WHITE)
    g2.drawOval(playerX.toInt - 9, playerY.toInt - 23, 18, 18)
    g2.setColor(new Color(245, 245, 232))
    g2.drawString(playerName, playerX.toInt - 25, playerY.toInt - 31)
  }

  def drawGate(g2: Graphics2D): Unit = {
    val gateColor = if (currentShardCount() >= 4) new Color(138, 255, 198) else new Color(120, 135, 145)
    g2.setStroke(new BasicStroke(6.0f))
    g2.setColor(new Color(gateColor.getRed, gateColor.getGreen, gateColor.getBlue, 65))
    g2.fillOval(870, 285, 75, 135)
    g2.setColor(gateColor)
    g2.drawOval(870, 285, 75, 135)
    g2.drawOval(879, 295, 57, 115)
    g2.setFont(new Font("SansSerif", Font.BOLD, 12))
    g2.drawString("GATE", 883, 440)
  }

  def drawBoss(g2: Graphics2D): Unit = {
    val bossColor = new Color(35, 23, 52)
    g2.setColor(new Color(180, 65, 210, 55))
    g2.fillOval(bossX.toInt - 42, bossY.toInt - 42, 84, 84)
    g2.setColor(bossColor)
    g2.fillOval(bossX.toInt - 26, bossY.toInt - 28, 52, 58)
    g2.setColor(new Color(255, 90, 110))
    g2.fillOval(bossX.toInt - 12, bossY.toInt - 8, 7, 7)
    g2.fillOval(bossX.toInt + 5, bossY.toInt - 8, 7, 7)
    g2.setColor(new Color(255, 190, 210))
    g2.drawString("CHAOS GUARDIAN", bossX.toInt - 48, bossY.toInt - 39)
    g2.setColor(new Color(50, 20, 30))
    g2.fillRoundRect(755, 118, 170, 13, 5, 5)
    g2.setColor(new Color(255, 95, 115))
    g2.fillRoundRect(755, 118, 170 * bossHealth / 6, 13, 5, 5)
  }

  def drawHud(g2: Graphics2D): Unit = {
    g2.setColor(new Color(5, 13, 20, 205))
    g2.fillRoundRect(16, 12, 968, 82, 18, 18)
    g2.setColor(new Color(227, 245, 242))
    g2.setFont(new Font("SansSerif", Font.BOLD, 17))
    g2.drawString("ELEMENTAL CHAOS REBORN", 32, 38)
    g2.setFont(new Font("SansSerif", Font.BOLD, 13))
    g2.drawString("Realm: " + realmNames(realmIndex), 32, 64)
    g2.drawString("Shards: " + currentShardCount() + "/4   Total: " + totalShards, 330, 38)
    g2.drawString("Health: " + playerHealth + "/5", 330, 64)
    g2.drawString("Energy: " + energy + "/100", 485, 38)
    g2.drawString("Score: " + score, 485, 64)
    g2.setColor(elementColors(selectedElement))
    g2.drawString("Element: " + elementNames(selectedElement) + "  [1-4]", 700, 38)
    g2.setColor(new Color(210, 225, 232))
    g2.drawString("F: POWER   Q: SHIELD   SPACE: DASH", 700, 64)

    g2.setColor(new Color(4, 12, 18, 195))
    g2.fillRoundRect(18, 657, 964, 30, 10, 10)
    g2.setColor(new Color(235, 246, 239))
    g2.setFont(new Font("SansSerif", Font.PLAIN, 12))
    g2.drawString(message, 30, 677)

    g2.setColor(new Color(245, 245, 245, 210))
    g2.setFont(new Font("SansSerif", Font.PLAIN, 11))
    g2.drawString("WASD/ARROWS MOVE  |  CLICK WALK  |  E GATE  |  B BASE  |  P PAUSE", 285, 635)
  }

  def drawOverlay(g2: Graphics2D, heading: String, subheading: String): Unit = {
    g2.setColor(new Color(3, 9, 15, 190))
    g2.fillRect(0, 0, getWidth, getHeight)
    g2.setColor(Color.WHITE)
    g2.setFont(new Font("SansSerif", Font.BOLD, 36))
    val width = g2.getFontMetrics.stringWidth(heading)
    g2.drawString(heading, (getWidth - width) / 2, 300)
    g2.setFont(new Font("SansSerif", Font.PLAIN, 17))
    val subWidth = g2.getFontMetrics.stringWidth(subheading)
    g2.drawString(subheading, (getWidth - subWidth) / 2, 345)
  }
}

// Kojo launch line: run the complete script to open the game window.
ElementalChaosRebornEvent9.main(Array[String]())