Code Sketch
Bixuu CrystalCoreRevolutionEvent3
Category: Programming
import java.awt.{BasicStroke, Color, Dimension, Font, FontMetrics, GradientPaint, Graphics, Graphics2D, RenderingHints}
import java.awt.event.{ActionEvent, ActionListener, KeyEvent, KeyListener, MouseEvent, MouseListener, WindowAdapter, WindowEvent}
import javax.swing.{JFrame, JPanel, SwingUtilities, Timer, WindowConstants}
import scala.collection.mutable
import scala.collection.mutable.ArrayBuffer
import scala.util.Random
object CrystalCoreRevolutionEvent3 {
private val VIEW_W = 1100
private val VIEW_H = 760
def main(args: Array[String]): Unit = {
SwingUtilities.invokeLater(new Runnable {
override def run(): Unit = {
val frame = new JFrame("INFINITY REALMS SEASON 3 - CRYSTAL CORE REVOLUTION")
val panel = new CrystalGamePanel()
frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE)
frame.setContentPane(panel)
frame.pack()
frame.setResizable(false)
frame.setLocationRelativeTo(null)
frame.addWindowListener(new WindowAdapter {
override def windowClosing(e: WindowEvent): Unit = panel.stopGame()
override def windowClosed(e: WindowEvent): Unit = panel.stopGame()
})
frame.setVisible(true)
panel.requestFocusInWindow()
}
})
}
private case class Crystal(var x: Double, var y: Double, var kind: Int, var collected: Boolean)
private case class Wisp(var x: Double, var y: Double, var stunned: Double, var phase: Double)
private case class TreeDecoration(x: Int, y: Int, size: Int, kind: Int)
private class CrystalGamePanel extends JPanel with ActionListener with KeyListener with MouseListener {
private val SCREEN_MENU = 0
private val SCREEN_LOGIN = 1
private val SCREEN_AVATAR = 2
private val SCREEN_PLAY = 3
private val SCREEN_POWERS = 4
private val SCREEN_PAUSE = 5
private val SCREEN_WIN = 6
private val SCREEN_LOST = 7
private val SCREEN_HELP = 8
private val rng = new Random()
private val keys = mutable.Set[Int]()
private val crystals = ArrayBuffer[Crystal]()
private val wisps = ArrayBuffer[Wisp]()
private val decorations = ArrayBuffer[TreeDecoration]()
private val timer = new Timer(16, this)
private var screen = SCREEN_MENU
private var playerName = "Crystal Explorer"
private var editingName = false
private var avatar = 0
private var realm = 0
private var playerX = 105.0
private var playerY = 390.0
private var targetX = -1.0
private var targetY = -1.0
private var health = 4
private var coins = 0
private var totalCrystals = 0
private var realmCrystals = 0
private var energy = 100.0
private var dashTime = 0.0
private var dashCooldown = 0.0
private var shieldTime = 0.0
private var pulseTime = 0.0
private var damageCooldown = 0.0
private var message = "Collect six crystals in each realm!"
private var messageTime = 5.0
private var elapsed = 0.0
private var coreAwakened = false
private var lastFrameNanos = System.nanoTime()
private var pulseCooldown = 0.0
private var healCooldown = 0.0
setPreferredSize(new Dimension(VIEW_W, VIEW_H))
setFocusable(true)
setDoubleBuffered(true)
addKeyListener(this)
addMouseListener(this)
setToolTipText("WASD: move | SPACE: dash | Q: shield | F: Nova Pulse | H: Heal | E: interact | C: powers")
timer.start()
def stopGame(): Unit = {
if (timer.isRunning) timer.stop()
}
private def showMessage(text: String, seconds: Double): Unit = {
message = text
messageTime = seconds
}
private def startNewGame(): Unit = {
realm = 0
playerX = 105.0
playerY = 390.0
targetX = -1.0
targetY = -1.0
health = 4
coins = 0
totalCrystals = 0
realmCrystals = 0
energy = 100.0
dashTime = 0.0
dashCooldown = 0.0
shieldTime = 0.0
pulseTime = 0.0
damageCooldown = 0.0
pulseCooldown = 0.0
healCooldown = 0.0
coreAwakened = false
buildRealm()
screen = SCREEN_PLAY
showMessage("Realm 1: enter the Prism Grove and collect 6 crystals!", 5.0)
requestFocusInWindow()
}
private def buildRealm(): Unit = {
crystals.clear()
wisps.clear()
decorations.clear()
var i = 0
while (i < 6) {
val x = 220.0 + rng.nextInt(790).toDouble
val y = 175.0 + rng.nextInt(475).toDouble
val kind = (i + realm) % 4
crystals += Crystal(x, y, kind, false)
i += 1
}
val wispCount = 2 + realm
i = 0
while (i < wispCount) {
val x = 380.0 + rng.nextInt(620).toDouble
val y = 170.0 + rng.nextInt(470).toDouble
wisps += Wisp(x, y, 0.0, rng.nextDouble() * 6.0)
i += 1
}
i = 0
while (i < 34) {
decorations += TreeDecoration(35 + rng.nextInt(1020), 145 + rng.nextInt(540), 22 + rng.nextInt(35), rng.nextInt(3))
i += 1
}
realmCrystals = 0
}
private def playerSpeed: Double = {
val bonus = math.min(1.2, totalCrystals.toDouble * 0.035)
2.75 + bonus + (if (dashTime > 0.0) 4.0 else 0.0)
}
private 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)
}
private def collectNearbyCrystal(): Unit = {
var found = false
var i = 0
while (i < crystals.length && !found) {
val c = crystals(i)
if (!c.collected && distance(playerX, playerY, c.x, c.y) < 38.0) {
c.collected = true
realmCrystals += 1
totalCrystals += 1
coins += 20 + realm * 10
energy = math.min(100.0, energy + 14.0)
showMessage("Crystal collected! +" + (20 + realm * 10) + " coins", 2.0)
found = true
if (realmCrystals == 6) showMessage("Realm Gate activated! Go to the glowing gate and press E.", 4.0)
}
i += 1
}
}
private def interact(): Unit = {
collectNearbyCrystal()
if (realmCrystals >= 6 && distance(playerX, playerY, 1010.0, 390.0) < 100.0) {
if (realm < 2) {
realm += 1
playerX = 95.0
playerY = 390.0
targetX = -1.0
targetY = -1.0
buildRealm()
energy = math.min(100.0, energy + 25.0)
showMessage("Welcome to " + realmName(realm) + "! Find six new crystals.", 4.0)
} else {
coreAwakened = true
screen = SCREEN_WIN
showMessage("The Crystal Core is awake!", 8.0)
}
} else if (realmCrystals < 6) {
showMessage("You need " + (6 - realmCrystals) + " more crystals to open this gate.", 2.0)
} else {
showMessage("Move closer to the glowing Realm Gate and press E.", 2.0)
}
}
private def startDash(): Unit = {
if (screen == SCREEN_PLAY && dashCooldown <= 0.0 && energy >= 12.0) {
dashTime = 0.22
dashCooldown = 1.0
energy -= 12.0
}
}
private def useShield(): Unit = {
if (totalCrystals >= 3 && energy >= 25.0 && shieldTime <= 0.0) {
energy -= 25.0
shieldTime = 3.5
showMessage("CRYSTAL GUARD activated!", 1.5)
} else if (totalCrystals < 3) {
showMessage("Crystal Guard unlocks at 3 collected crystals.", 2.0)
} else {
showMessage("Not enough energy or shield is already active.", 1.5)
}
}
private def useNovaPulse(): Unit = {
if (totalCrystals >= 6 && energy >= 35.0 && pulseCooldown <= 0.0) {
energy -= 35.0
pulseCooldown = 5.0
pulseTime = 0.55
var i = 0
while (i < wisps.length) {
val w = wisps(i)
if (distance(playerX, playerY, w.x, w.y) < 205.0) w.stunned = 3.5
i += 1
}
showMessage("NOVA PULSE! Nearby Wisps are stunned.", 2.0)
} else if (totalCrystals < 6) {
showMessage("Nova Pulse unlocks at 6 collected crystals.", 2.0)
} else {
showMessage("Nova Pulse is recharging or energy is low.", 1.5)
}
}
private def useHeal(): Unit = {
if (totalCrystals >= 9 && health < 4 && energy >= 40.0 && healCooldown <= 0.0) {
energy -= 40.0
health += 1
healCooldown = 7.0
showMessage("Verdant Heal restored one heart.", 2.0)
} else if (totalCrystals < 9) {
showMessage("Verdant Heal unlocks at 9 collected crystals.", 2.0)
} else if (health >= 4) {
showMessage("Your health is already full.", 1.5)
} else {
showMessage("Verdant Heal is recharging or energy is low.", 1.5)
}
}
private def updateGame(dt: Double): Unit = {
elapsed += dt
if (messageTime > 0.0) messageTime -= dt
if (dashTime > 0.0) dashTime -= dt
if (dashCooldown > 0.0) dashCooldown -= dt
if (shieldTime > 0.0) shieldTime -= dt
if (pulseTime > 0.0) pulseTime -= dt
if (damageCooldown > 0.0) damageCooldown -= dt
if (pulseCooldown > 0.0) pulseCooldown -= dt
if (healCooldown > 0.0) healCooldown -= dt
energy = math.min(100.0, energy + 2.0 * dt)
var dx = 0.0
var dy = 0.0
if (keys.contains(KeyEvent.VK_A) || keys.contains(KeyEvent.VK_LEFT)) dx -= 1.0
if (keys.contains(KeyEvent.VK_D) || keys.contains(KeyEvent.VK_RIGHT)) dx += 1.0
if (keys.contains(KeyEvent.VK_W) || keys.contains(KeyEvent.VK_UP)) dy -= 1.0
if (keys.contains(KeyEvent.VK_S) || keys.contains(KeyEvent.VK_DOWN)) dy += 1.0
if (dx == 0.0 && dy == 0.0 && targetX >= 0.0) {
val tx = targetX - playerX
val ty = targetY - playerY
val d = math.sqrt(tx * tx + ty * ty)
if (d > 8.0) {
dx = tx / d
dy = ty / d
} else {
targetX = -1.0
targetY = -1.0
}
}
if (dx != 0.0 || dy != 0.0) {
val length = math.sqrt(dx * dx + dy * dy)
playerX += (dx / length) * playerSpeed
playerY += (dy / length) * playerSpeed
targetX = -1.0
targetY = -1.0
}
playerX = math.max(42.0, math.min(1058.0, playerX))
playerY = math.max(142.0, math.min(692.0, playerY))
collectNearbyCrystal()
var i = 0
while (i < wisps.length) {
val w = wisps(i)
if (w.stunned > 0.0) {
w.stunned -= dt
} else {
val d = distance(playerX, playerY, w.x, w.y)
if (d < 320.0 && d > 1.0) {
val speed = 0.72 + realm.toDouble * 0.16
w.x += ((playerX - w.x) / d) * speed
w.y += ((playerY - w.y) / d) * speed
}
w.phase += dt * 2.0
if (d < 31.0 && damageCooldown <= 0.0 && shieldTime <= 0.0) {
health -= 1
damageCooldown = 1.3
playerX = math.max(42.0, playerX - 28.0)
showMessage("A Corrupted Wisp touched you! Use Dash or Crystal Guard.", 2.0)
if (health <= 0) screen = SCREEN_LOST
}
}
i += 1
}
}
override def actionPerformed(e: ActionEvent): Unit = {
val now = System.nanoTime()
var dt = (now - lastFrameNanos).toDouble / 1000000000.0
lastFrameNanos = now
if (dt > 0.05) dt = 0.05
if (screen == SCREEN_PLAY) updateGame(dt)
repaint()
}
private def realmName(index: Int): String = {
if (index == 0) "Prism Grove"
else if (index == 1) "Crystal Tide Cavern"
else "Aurora Shard Summit"
}
private def realmColor(index: Int): Color = {
if (index == 0) new Color(31, 105, 74)
else if (index == 1) new Color(31, 83, 132)
else new Color(91, 57, 137)
}
private def drawCentered(g: Graphics2D, text: String, x: Int, y: Int): Unit = {
val fm = g.getFontMetrics
g.drawString(text, x - fm.stringWidth(text) / 2, y)
}
private def drawButton(g: Graphics2D, x: Int, y: Int, w: Int, h: Int, label: String, accent: Color): Unit = {
g.setColor(new Color(7, 18, 31, 205))
g.fillRoundRect(x + 3, y + 5, w, h, 18, 18)
g.setPaint(new GradientPaint(x.toFloat, y.toFloat, accent, (x + w).toFloat, (y + h).toFloat, new Color(25, 46, 65)))
g.fillRoundRect(x, y, w, h, 18, 18)
g.setColor(new Color(220, 250, 255, 210))
g.setStroke(new BasicStroke(2.0f))
g.drawRoundRect(x, y, w, h, 18, 18)
g.setFont(new Font("Dialog", Font.BOLD, 18))
g.setColor(Color.WHITE)
drawCentered(g, label, x + w / 2, y + h / 2 + 6)
}
private def drawBackground(g: Graphics2D): Unit = {
val top = if (realm == 0) new Color(12, 39, 35) else if (realm == 1) new Color(10, 27, 58) else new Color(30, 18, 57)
val bottom = if (realm == 0) new Color(28, 86, 60) else if (realm == 1) new Color(30, 74, 112) else new Color(79, 43, 112)
g.setPaint(new GradientPaint(0, 105, top, 0, VIEW_H, bottom))
g.fillRect(0, 100, VIEW_W, VIEW_H - 100)
var i = 0
while (i < 80) {
val x = (i * 137 + 29) % VIEW_W
val y = 115 + ((i * 83 + 17) % 610)
val pulse = (math.sin(elapsed * 1.8 + i.toDouble) + 1.0) * 0.5
val alpha = (65 + pulse * 150).toInt
g.setColor(new Color(185, 245, 255, alpha))
g.fillOval(x, y, 2 + (i % 3), 2 + (i % 3))
i += 1
}
g.setColor(new Color(8, 20, 30, 90))
g.fillOval(-90, 560, 430, 190)
g.fillOval(310, 570, 470, 180)
g.fillOval(760, 565, 430, 190)
for (d <- decorations) {
val trunk = if (realm == 0) new Color(46, 76, 57, 190) else if (realm == 1) new Color(63, 83, 114, 180) else new Color(73, 57, 102, 180)
g.setColor(trunk)
g.fillRoundRect(d.x, d.y, 8, d.size, 6, 6)
val crown = if (realm == 0) new Color(44 + d.kind * 12, 125 + d.kind * 8, 89 + d.kind * 10, 155) else if (realm == 1) new Color(77, 160 + d.kind * 10, 190 + d.kind * 8, 150) else new Color(131 + d.kind * 12, 83, 173 + d.kind * 10, 155)
g.setColor(crown)
g.fillOval(d.x - d.size / 2, d.y - d.size, d.size + 8, d.size + 12)
}
}
private def drawHud(g: Graphics2D): Unit = {
g.setColor(new Color(5, 14, 28, 235))
g.fillRect(0, 0, VIEW_W, 105)
g.setColor(new Color(119, 235, 221))
g.setFont(new Font("Dialog", Font.BOLD, 24))
g.drawString("CRYSTAL CORE REVOLUTION", 24, 34)
g.setFont(new Font("Dialog", Font.PLAIN, 14))
g.setColor(new Color(213, 229, 245))
g.drawString("Explorer: " + playerName + " | Realm: " + realmName(realm), 26, 59)
g.drawString("Crystals: " + totalCrystals + " Realm: " + realmCrystals + "/6 | Coins: " + coins, 26, 82)
g.setColor(new Color(25, 42, 60))
g.fillRoundRect(705, 19, 190, 17, 9, 9)
g.setColor(new Color(64, 218, 192))
g.fillRoundRect(705, 19, (energy * 1.9).toInt, 17, 9, 9)
g.setColor(Color.WHITE)
g.setFont(new Font("Dialog", Font.BOLD, 12))
g.drawString("ENERGY " + energy.toInt + "%", 710, 50)
g.setColor(new Color(45, 28, 47))
g.fillRoundRect(920, 19, 125, 17, 9, 9)
g.setColor(new Color(244, 110, 151))
g.fillRoundRect(920, 19, (health * 31).toInt, 17, 9, 9)
g.setColor(Color.WHITE)
g.drawString("HEARTS " + health + "/4", 925, 50)
g.setColor(new Color(230, 238, 250))
g.drawString("C: POWERS", 930, 80)
}
private def drawCrystal(g: Graphics2D, c: Crystal): Unit = {
if (!c.collected) {
val color = if (c.kind == 0) new Color(78, 255, 207) else if (c.kind == 1) new Color(112, 190, 255) else if (c.kind == 2) new Color(212, 137, 255) else new Color(255, 221, 116)
val glow = (math.sin(elapsed * 4.0 + c.x * 0.01) + 1.0) * 0.5
g.setColor(new Color(color.getRed, color.getGreen, color.getBlue, 45 + (glow * 55).toInt))
g.fillOval(c.x.toInt - 22, c.y.toInt - 22, 44, 44)
g.setColor(color)
val px = c.x.toInt
val py = c.y.toInt
val poly = new java.awt.Polygon()
poly.addPoint(px, py - 17)
poly.addPoint(px + 12, py - 3)
poly.addPoint(px + 7, py + 14)
poly.addPoint(px - 7, py + 14)
poly.addPoint(px - 12, py - 3)
g.fillPolygon(poly)
g.setColor(new Color(255, 255, 255, 190))
g.drawLine(px - 3, py - 8, px + 1, py + 7)
}
}
private def drawPlayer(g: Graphics2D): Unit = {
if (shieldTime > 0.0) {
g.setColor(new Color(113, 226, 255, 65))
g.fillOval(playerX.toInt - 27, playerY.toInt - 27, 54, 54)
g.setColor(new Color(142, 239, 255, 220))
g.setStroke(new BasicStroke(2.0f))
g.drawOval(playerX.toInt - 27, playerY.toInt - 27, 54, 54)
}
val colors = Array(new Color(255, 194, 87), new Color(105, 225, 196), new Color(173, 143, 255), new Color(247, 133, 183))
g.setColor(new Color(0, 0, 0, 90))
g.fillOval(playerX.toInt - 16, playerY.toInt + 11, 32, 9)
g.setColor(colors(avatar))
g.fillOval(playerX.toInt - 14, playerY.toInt - 19, 28, 30)
g.setColor(new Color(248, 251, 255))
g.fillOval(playerX.toInt - 7, playerY.toInt - 11, 5, 5)
g.fillOval(playerX.toInt + 3, playerY.toInt - 11, 5, 5)
g.setColor(new Color(17, 31, 45))
g.fillOval(playerX.toInt - 5, playerY.toInt - 10, 2, 3)
g.fillOval(playerX.toInt + 5, playerY.toInt - 10, 2, 3)
g.setFont(new Font("Dialog", Font.BOLD, 11))
g.setColor(Color.WHITE)
drawCentered(g, playerName, playerX.toInt, playerY.toInt - 26)
}
private def drawWisp(g: Graphics2D, w: Wisp): Unit = {
val x = w.x.toInt
val y = w.y.toInt
if (w.stunned <= 0.0) {
g.setColor(new Color(197, 123, 255, 45))
g.fillOval(x - 22, y - 25, 44, 44)
g.setColor(new Color(189, 157, 255, 215))
} else {
g.setColor(new Color(125, 237, 255, 220))
}
g.fillOval(x - 13, y - 16, 26, 28)
g.setColor(new Color(24, 22, 51))
g.fillOval(x - 7, y - 7, 4, 5)
g.fillOval(x + 3, y - 7, 4, 5)
g.setColor(new Color(236, 225, 255, 170))
g.drawArc(x - 8, y - 2, 16, 12, 190, 160)
}
private def drawGate(g: Graphics2D): Unit = {
val gateColor = if (realmCrystals >= 6) new Color(104, 255, 205) else new Color(118, 137, 160)
val glow = (math.sin(elapsed * 2.5) + 1.0) * 0.5
g.setColor(new Color(gateColor.getRed, gateColor.getGreen, gateColor.getBlue, 35 + (glow * 55).toInt))
g.fillOval(969, 338, 82, 105)
g.setColor(gateColor)
g.setStroke(new BasicStroke(5.0f))
g.drawOval(982, 345, 55, 87)
g.drawArc(990, 353, 39, 69, 0, 180)
g.setFont(new Font("Dialog", Font.BOLD, 12))
g.setColor(Color.WHITE)
drawCentered(g, if (realm == 2) "CORE" else "GATE", 1010, 462)
}
private def drawMessage(g: Graphics2D): Unit = {
if (messageTime > 0.0) {
g.setColor(new Color(5, 12, 25, 205))
g.fillRoundRect(230, 112, 640, 42, 15, 15)
g.setColor(new Color(205, 250, 243))
g.setFont(new Font("Dialog", Font.BOLD, 14))
drawCentered(g, message, 550, 138)
}
}
private def drawMenu(g: Graphics2D): Unit = {
g.setPaint(new GradientPaint(0, 0, new Color(7, 23, 43), 0, VIEW_H, new Color(15, 73, 76)))
g.fillRect(0, 0, VIEW_W, VIEW_H)
var i = 0
while (i < 85) {
val x = (i * 113 + 31) % VIEW_W
val y = (i * 71 + 19) % VIEW_H
g.setColor(new Color(116, 247, 225, 90 + (i % 5) * 25))
g.fillOval(x, y, 2 + (i % 4), 2 + (i % 4))
i += 1
}
g.setColor(new Color(83, 238, 213, 50))
g.fillOval(375, 100, 350, 350)
g.setColor(new Color(12, 45, 60, 220))
g.fillOval(410, 135, 280, 280)
g.setFont(new Font("Dialog", Font.BOLD, 43))
g.setColor(new Color(112, 255, 214))
drawCentered(g, "CRYSTAL CORE", 550, 260)
g.setColor(Color.WHITE)
drawCentered(g, "REVOLUTION", 550, 310)
g.setFont(new Font("Dialog", Font.PLAIN, 19))
g.setColor(new Color(207, 237, 244))
drawCentered(g, "INFINITY REALMS SEASON 3 | CRYSTAL POWERS", 550, 365)
drawButton(g, 405, 430, 290, 58, "START ADVENTURE", new Color(39, 173, 145))
drawButton(g, 405, 505, 290, 48, "HOW TO PLAY", new Color(76, 109, 184))
g.setFont(new Font("Dialog", Font.PLAIN, 13))
g.setColor(new Color(177, 212, 220))
drawCentered(g, "Explore three realms. Collect crystals. Awaken the Core.", 550, 600)
}
private def drawLogin(g: Graphics2D): Unit = {
drawMenu(g)
g.setColor(new Color(5, 16, 29, 235))
g.fillRoundRect(330, 220, 440, 330, 28, 28)
g.setColor(new Color(119, 246, 220))
g.setFont(new Font("Dialog", Font.BOLD, 27))
drawCentered(g, "EXPLORER LOGIN", 550, 275)
g.setFont(new Font("Dialog", Font.PLAIN, 16))
g.setColor(Color.WHITE)
drawCentered(g, "Type your name (max 18 characters):", 550, 330)
g.setColor(new Color(21, 47, 64))
g.fillRoundRect(390, 355, 320, 48, 12, 12)
g.setColor(new Color(132, 242, 219))
g.drawRoundRect(390, 355, 320, 48, 12, 12)
g.setFont(new Font("Dialog", Font.BOLD, 21))
drawCentered(g, playerName + (if (editingName) "|" else ""), 550, 385)
drawButton(g, 425, 435, 250, 52, "CONTINUE", new Color(39, 173, 145))
g.setFont(new Font("Dialog", Font.PLAIN, 13))
g.setColor(new Color(200, 221, 232))
drawCentered(g, "Click the name box, type your name, then press ENTER.", 550, 515)
}
private def drawAvatar(g: Graphics2D): Unit = {
drawBackground(g)
g.setColor(new Color(5, 14, 28, 225))
g.fillRoundRect(160, 150, 780, 470, 28, 28)
g.setColor(new Color(125, 247, 220))
g.setFont(new Font("Dialog", Font.BOLD, 30))
drawCentered(g, "CHOOSE YOUR CRYSTAL GUARDIAN", 550, 205)
val names = Array("PRISM RANGER", "TIDE MAGE", "AURORA KNIGHT", "NOVA KEEPER")
val colors = Array(new Color(255, 194, 87), new Color(105, 225, 196), new Color(173, 143, 255), new Color(247, 133, 183))
var i = 0
while (i < 4) {
val x = 205 + i * 176
g.setColor(if (avatar == i) new Color(47, 109, 105) else new Color(24, 42, 62))
g.fillRoundRect(x, 260, 150, 205, 18, 18)
g.setColor(if (avatar == i) new Color(141, 255, 225) else new Color(109, 140, 166))
g.drawRoundRect(x, 260, 150, 205, 18, 18)
g.setColor(colors(i))
g.fillOval(x + 47, 290, 56, 56)
g.setColor(Color.WHITE)
g.setFont(new Font("Dialog", Font.BOLD, 12))
drawCentered(g, names(i), x + 75, 390)
g.setFont(new Font("Dialog", Font.PLAIN, 11))
drawCentered(g, "Click to select", x + 75, 420)
if (avatar == i) drawCentered(g, "SELECTED", x + 75, 447)
i += 1
}
drawButton(g, 400, 525, 300, 55, "ENTER THE CRYSTAL REALMS", new Color(45, 174, 148))
}
private def drawPlay(g: Graphics2D): Unit = {
drawBackground(g)
drawHud(g)
drawGate(g)
var i = 0
while (i < crystals.length) {
drawCrystal(g, crystals(i))
i += 1
}
i = 0
while (i < wisps.length) {
drawWisp(g, wisps(i))
i += 1
}
if (pulseTime > 0.0) {
val size = (420.0 * (1.0 - pulseTime / 0.55)).toInt
g.setColor(new Color(103, 237, 255, 95))
g.setStroke(new BasicStroke(5.0f))
g.drawOval(playerX.toInt - size / 2, playerY.toInt - size / 2, size, size)
}
drawPlayer(g)
g.setColor(new Color(5, 14, 28, 205))
g.fillRoundRect(18, 665, 1064, 48, 13, 13)
g.setColor(new Color(215, 239, 246))
g.setFont(new Font("Dialog", Font.PLAIN, 13))
g.drawString("WASD / Arrows: Move SPACE: Dash Q: Guard (3 crystals) F: Nova Pulse (6) H: Heal (9) E: Gate C: Power Book P: Pause", 32, 694)
drawMessage(g)
}
private def drawPowers(g: Graphics2D): Unit = {
drawBackground(g)
g.setColor(new Color(5, 14, 28, 235))
g.fillRoundRect(180, 125, 740, 500, 28, 28)
g.setColor(new Color(132, 248, 224))
g.setFont(new Font("Dialog", Font.BOLD, 31))
drawCentered(g, "CRYSTAL POWER ARCHIVE", 550, 185)
val labels = Array("PRISM DASH", "CRYSTAL GUARD", "NOVA PULSE", "VERDANT HEAL")
val desc = Array("SPACE | Quick energy burst", "Q | Unlock at 3 crystals", "F | Unlock at 6 crystals", "H | Unlock at 9 crystals")
val unlocked = Array(true, totalCrystals >= 3, totalCrystals >= 6, totalCrystals >= 9)
var i = 0
while (i < 4) {
val x = 235 + (i % 2) * 315
val y = 230 + (i / 2) * 150
g.setColor(if (unlocked(i)) new Color(24, 78, 77) else new Color(35, 39, 55))
g.fillRoundRect(x, y, 270, 112, 18, 18)
g.setColor(if (unlocked(i)) new Color(112, 248, 218) else new Color(111, 122, 144))
g.drawRoundRect(x, y, 270, 112, 18, 18)
g.setFont(new Font("Dialog", Font.BOLD, 19))
g.setColor(Color.WHITE)
drawCentered(g, labels(i), x + 135, y + 38)
g.setFont(new Font("Dialog", Font.PLAIN, 13))
g.setColor(new Color(210, 226, 239))
drawCentered(g, desc(i), x + 135, y + 68)
drawCentered(g, if (unlocked(i)) "UNLOCKED" else "LOCKED", x + 135, y + 93)
i += 1
}
drawButton(g, 425, 565, 250, 45, "BACK TO ADVENTURE", new Color(55, 125, 157))
}
private def drawPause(g: Graphics2D): Unit = {
drawPlay(g)
g.setColor(new Color(3, 10, 21, 205))
g.fillRect(0, 100, VIEW_W, VIEW_H - 100)
g.setColor(new Color(118, 246, 220))
g.setFont(new Font("Dialog", Font.BOLD, 38))
drawCentered(g, "ADVENTURE PAUSED", 550, 310)
drawButton(g, 415, 365, 270, 52, "RESUME", new Color(38, 160, 133))
drawButton(g, 415, 435, 270, 52, "RESTART REALM", new Color(80, 105, 168))
drawButton(g, 415, 505, 270, 52, "MAIN MENU", new Color(125, 75, 123))
}
private def drawWin(g: Graphics2D): Unit = {
drawMenu(g)
g.setColor(new Color(4, 17, 29, 235))
g.fillRoundRect(250, 190, 600, 390, 28, 28)
g.setFont(new Font("Dialog", Font.BOLD, 36))
g.setColor(new Color(135, 255, 220))
drawCentered(g, "THE CORE IS AWAKE!", 550, 275)
g.setFont(new Font("Dialog", Font.PLAIN, 19))
g.setColor(Color.WHITE)
drawCentered(g, "You restored balance to all three Crystal Realms.", 550, 335)
drawCentered(g, "Crystals: " + totalCrystals + " Coins: " + coins, 550, 375)
drawButton(g, 400, 430, 300, 55, "PLAY AGAIN", new Color(42, 173, 142))
}
private def drawLost(g: Graphics2D): Unit = {
drawMenu(g)
g.setColor(new Color(5, 12, 26, 238))
g.fillRoundRect(280, 215, 540, 330, 25, 25)
g.setColor(new Color(255, 160, 175))
g.setFont(new Font("Dialog", Font.BOLD, 36))
drawCentered(g, "THE WISPS OVERPOWERED YOU", 550, 300)
g.setColor(Color.WHITE)
g.setFont(new Font("Dialog", Font.PLAIN, 17))
drawCentered(g, "Collect crystals to unlock stronger powers and try again.", 550, 355)
drawButton(g, 415, 420, 270, 55, "RETRY ADVENTURE", new Color(47, 151, 139))
}
private def drawHelp(g: Graphics2D): Unit = {
drawMenu(g)
g.setColor(new Color(4, 17, 31, 238))
g.fillRoundRect(220, 155, 660, 460, 24, 24)
g.setColor(new Color(125, 246, 220))
g.setFont(new Font("Dialog", Font.BOLD, 30))
drawCentered(g, "HOW TO PLAY", 550, 215)
val lines = Array(
"Explore three magical realms and collect six crystals in each.",
"Walk with WASD or arrow keys. Click the map to move there.",
"SPACE: Prism Dash | Q: Crystal Guard (3 crystals)",
"F: Nova Pulse (6 crystals) | H: Verdant Heal (9 crystals)",
"Wisps follow you. Use your powers and avoid touching them.",
"When you have six crystals, reach the glowing gate and press E.",
"Complete all three realms to awaken the Crystal Core."
)
g.setFont(new Font("Dialog", Font.PLAIN, 16))
g.setColor(Color.WHITE)
var i = 0
while (i < lines.length) {
drawCentered(g, lines(i), 550, 280 + i * 42)
i += 1
}
drawButton(g, 425, 565, 250, 42, "BACK", new Color(58, 120, 150))
}
override def paintComponent(graphics: Graphics): Unit = {
super.paintComponent(graphics)
val g = graphics.create().asInstanceOf[Graphics2D]
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON)
g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY)
if (screen == SCREEN_MENU) drawMenu(g)
else if (screen == SCREEN_LOGIN) drawLogin(g)
else if (screen == SCREEN_AVATAR) drawAvatar(g)
else if (screen == SCREEN_PLAY) drawPlay(g)
else if (screen == SCREEN_POWERS) drawPowers(g)
else if (screen == SCREEN_PAUSE) drawPause(g)
else if (screen == SCREEN_WIN) drawWin(g)
else if (screen == SCREEN_LOST) drawLost(g)
else if (screen == SCREEN_HELP) drawHelp(g)
g.dispose()
}
private def inside(x: Int, y: Int, bx: Int, by: Int, bw: Int, bh: Int): Boolean = {
x >= bx && x <= bx + bw && y >= by && y <= by + bh
}
override def mousePressed(e: MouseEvent): Unit = {
val x = e.getX
val y = e.getY
if (screen == SCREEN_MENU) {
if (inside(x, y, 405, 430, 290, 58)) screen = SCREEN_LOGIN
else if (inside(x, y, 405, 505, 290, 48)) screen = SCREEN_HELP
} else if (screen == SCREEN_LOGIN) {
if (inside(x, y, 390, 355, 320, 48)) editingName = true
else if (inside(x, y, 425, 435, 250, 52)) {
if (playerName.trim.length == 0) playerName = "Crystal Explorer"
editingName = false
screen = SCREEN_AVATAR
}
} else if (screen == SCREEN_AVATAR) {
var i = 0
while (i < 4) {
val bx = 205 + i * 176
if (inside(x, y, bx, 260, 150, 205)) avatar = i
i += 1
}
if (inside(x, y, 400, 525, 300, 55)) startNewGame()
} else if (screen == SCREEN_PLAY) {
if (x > 900 && y < 95) screen = SCREEN_POWERS
else if (y > 110 && y < 660) {
targetX = x.toDouble
targetY = y.toDouble
}
} else if (screen == SCREEN_POWERS) {
if (inside(x, y, 425, 565, 250, 45)) screen = SCREEN_PLAY
} else if (screen == SCREEN_PAUSE) {
if (inside(x, y, 415, 365, 270, 52)) screen = SCREEN_PLAY
else if (inside(x, y, 415, 435, 270, 52)) startNewGame()
else if (inside(x, y, 415, 505, 270, 52)) screen = SCREEN_MENU
} else if (screen == SCREEN_WIN) {
if (inside(x, y, 400, 430, 300, 55)) startNewGame()
} else if (screen == SCREEN_LOST) {
if (inside(x, y, 415, 420, 270, 55)) startNewGame()
} else if (screen == SCREEN_HELP) {
if (inside(x, y, 425, 565, 250, 42)) screen = SCREEN_MENU
}
requestFocusInWindow()
repaint()
}
override def keyPressed(e: KeyEvent): Unit = {
val code = e.getKeyCode
val alreadyDown = keys.contains(code)
keys += code
if (!alreadyDown) {
if (screen == SCREEN_PLAY) {
if (code == KeyEvent.VK_SPACE) startDash()
else if (code == KeyEvent.VK_Q) useShield()
else if (code == KeyEvent.VK_F) useNovaPulse()
else if (code == KeyEvent.VK_H) useHeal()
else if (code == KeyEvent.VK_E) interact()
else if (code == KeyEvent.VK_C) screen = SCREEN_POWERS
else if (code == KeyEvent.VK_P || code == KeyEvent.VK_ESCAPE) screen = SCREEN_PAUSE
} else if (screen == SCREEN_PAUSE && (code == KeyEvent.VK_P || code == KeyEvent.VK_ESCAPE)) {
screen = SCREEN_PLAY
} else if (screen == SCREEN_POWERS && code == KeyEvent.VK_ESCAPE) {
screen = SCREEN_PLAY
} else if (screen == SCREEN_LOGIN && code == KeyEvent.VK_ENTER) {
if (playerName.trim.length == 0) playerName = "Crystal Explorer"
editingName = false
screen = SCREEN_AVATAR
} else if (screen == SCREEN_AVATAR && code == KeyEvent.VK_ENTER) {
startNewGame()
}
}
repaint()
}
override def keyReleased(e: KeyEvent): Unit = {
keys -= e.getKeyCode
}
override def keyTyped(e: KeyEvent): Unit = {
if (screen == SCREEN_LOGIN && editingName) {
val ch = e.getKeyChar
if (ch == '\b') {
if (playerName.length > 0) playerName = playerName.substring(0, playerName.length - 1)
} else if (!Character.isISOControl(ch) && playerName.length < 18) {
playerName += ch
}
repaint()
}
}
override def mouseClicked(e: MouseEvent): Unit = {}
override def mouseReleased(e: MouseEvent): Unit = {}
override def mouseEntered(e: MouseEvent): Unit = {}
override def mouseExited(e: MouseEvent): Unit = {}
}
}
CrystalCoreRevolutionEvent3.main(Array[String]())