Code Sketch
Bixuu NeonFutureUprisingEvent4.
Category: Programming
import java.awt.{BasicStroke, BorderLayout, CardLayout, Color, Dimension, Font, GradientPaint, Graphics, Graphics2D, RenderingHints}
import java.awt.event.{ActionEvent, ActionListener, KeyEvent, KeyListener, MouseEvent, MouseListener, WindowAdapter, WindowEvent}
import java.awt.geom.{Ellipse2D, RoundRectangle2D}
import javax.swing.{BorderFactory, JButton, JFrame, JLabel, JPanel, JPasswordField, SwingConstants, SwingUtilities, JTextField, Timer, WindowConstants}
import scala.collection.mutable.ArrayBuffer
import scala.util.Random
object NeonFutureUprisingEvent4 {
def main(args: Array[String]): Unit = {
SwingUtilities.invokeLater(new Runnable {
def run(): Unit = {
val app = new NeonFutureAppFrame()
app.setVisible(true)
}
})
}
}
class NeonFutureAppFrame extends JFrame("SPRING SEASON EVENT 4 - NEON FUTURE UPRISING") {
private val layoutCards = new CardLayout()
private val rootPanel = new JPanel(layoutCards)
private val gamePanel = new NeonCityGamePanel(new Runnable {
def run(): Unit = showMenu()
})
private var playerName = "PLAYER"
private val titleColor = new Color(92, 255, 238)
private val dark = new Color(8, 12, 35)
private val buttonColor = new Color(23, 43, 80)
private val loginPanel = new JPanel(new BorderLayout(12, 12))
private val nameField = new JTextField(18)
private val loginStatus = new JLabel("ENTER YOUR CALLSIGN TO CONNECT", SwingConstants.CENTER)
private val menuPanel = new JPanel(new BorderLayout(12, 12))
private val menuWelcome = new JLabel("WELCOME, PLAYER", SwingConstants.CENTER)
initLoginPanel()
initMenuPanel()
rootPanel.add(loginPanel, "LOGIN")
rootPanel.add(menuPanel, "MENU")
rootPanel.add(gamePanel, "GAME")
setContentPane(rootPanel)
setSize(1000, 700)
setMinimumSize(new Dimension(850, 620))
setLocationRelativeTo(null)
setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE)
addWindowListener(new WindowAdapter {
override def windowClosing(e: WindowEvent): Unit = gamePanel.stopGame()
})
layoutCards.show(rootPanel, "LOGIN")
private def styleButton(button: JButton): Unit = {
button.setForeground(Color.WHITE)
button.setBackground(buttonColor)
button.setFocusPainted(false)
button.setFont(new Font("SansSerif", Font.BOLD, 16))
button.setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createLineBorder(titleColor, 1),
BorderFactory.createEmptyBorder(12, 20, 12, 20)
))
}
private def initLoginPanel(): Unit = {
loginPanel.setBackground(dark)
val heading = new JLabel("NEON FUTURE UPRISING", SwingConstants.CENTER)
heading.setForeground(titleColor)
heading.setFont(new Font("SansSerif", Font.BOLD, 34))
val sub = new JLabel("A FUTURISTIC CITY ADVENTURE", SwingConstants.CENTER)
sub.setForeground(Color.WHITE)
sub.setFont(new Font("SansSerif", Font.PLAIN, 16))
val center = new JPanel()
center.setOpaque(false)
center.setLayout(new java.awt.GridBagLayout())
val c = new java.awt.GridBagConstraints()
c.gridx = 0
c.gridy = 0
c.insets = new java.awt.Insets(8, 8, 8, 8)
val prompt = new JLabel("PLAYER CALLSIGN")
prompt.setForeground(new Color(190, 220, 255))
prompt.setFont(new Font("SansSerif", Font.BOLD, 15))
center.add(prompt, c)
c.gridy = 1
nameField.setFont(new Font("SansSerif", Font.PLAIN, 19))
nameField.setHorizontalAlignment(SwingConstants.CENTER)
nameField.setBackground(new Color(18, 28, 58))
nameField.setForeground(Color.WHITE)
nameField.setCaretColor(Color.WHITE)
nameField.setBorder(BorderFactory.createLineBorder(titleColor, 2))
center.add(nameField, c)
c.gridy = 2
loginStatus.setForeground(new Color(255, 210, 110))
center.add(loginStatus, c)
c.gridy = 3
val loginButton = new JButton("CONNECT TO NEON CITY")
styleButton(loginButton)
loginButton.addActionListener(new ActionListener {
def actionPerformed(e: ActionEvent): Unit = {
val entered = nameField.getText.trim
if (entered.length == 0) {
loginStatus.setText("PLEASE ENTER A CALLSIGN FIRST")
} else {
playerName = entered.take(18)
menuWelcome.setText("WELCOME, " + playerName.toUpperCase)
layoutCards.show(rootPanel, "MENU")
}
}
})
center.add(loginButton, c)
val top = new JPanel(new BorderLayout())
top.setOpaque(false)
top.add(heading, BorderLayout.CENTER)
top.add(sub, BorderLayout.SOUTH)
top.setBorder(BorderFactory.createEmptyBorder(75, 20, 10, 20))
loginPanel.add(top, BorderLayout.NORTH)
loginPanel.add(center, BorderLayout.CENTER)
val footer = new JLabel("EVENT 04 | FUTURISTIC WORLD | OFFLINE ARCADE ADVENTURE", SwingConstants.CENTER)
footer.setForeground(new Color(130, 160, 205))
footer.setBorder(BorderFactory.createEmptyBorder(12, 10, 25, 10))
loginPanel.add(footer, BorderLayout.SOUTH)
}
private def initMenuPanel(): Unit = {
menuPanel.setBackground(dark)
val heading = new JLabel("NEON FUTURE UPRISING", SwingConstants.CENTER)
heading.setForeground(titleColor)
heading.setFont(new Font("SansSerif", Font.BOLD, 32))
menuWelcome.setForeground(Color.WHITE)
menuWelcome.setFont(new Font("SansSerif", Font.BOLD, 18))
val top = new JPanel(new BorderLayout(5, 8))
top.setOpaque(false)
top.add(heading, BorderLayout.CENTER)
top.add(menuWelcome, BorderLayout.SOUTH)
top.setBorder(BorderFactory.createEmptyBorder(55, 20, 20, 20))
val center = new JPanel(new java.awt.GridLayout(3, 1, 12, 12))
center.setOpaque(false)
center.setBorder(BorderFactory.createEmptyBorder(20, 250, 30, 250))
val play = new JButton("ENTER NEON CITY")
val how = new JButton("HOW TO PLAY")
val back = new JButton("BACK TO LOGIN")
styleButton(play)
styleButton(how)
styleButton(back)
play.addActionListener(new ActionListener {
def actionPerformed(e: ActionEvent): Unit = {
gamePanel.setPlayerName(playerName)
gamePanel.resetGame()
layoutCards.show(rootPanel, "GAME")
gamePanel.startGame()
SwingUtilities.invokeLater(new Runnable { def run(): Unit = gamePanel.requestFocusInWindow() })
}
})
how.addActionListener(new ActionListener {
def actionPerformed(e: ActionEvent): Unit = {
javax.swing.JOptionPane.showMessageDialog(NeonFutureAppFrame.this,
"WASD / ARROWS = MOVE\nSPACE = HOVER DASH\nE = RESCUE / DELIVER CITIZEN\nF = PULSE TAG (STUN DRONES)\nCOLLECT NEON CORES, RESCUE CITIZENS, RETURN TO BASE, THEN ACTIVATE THE EXIT GATE.",
"HOW TO PLAY", javax.swing.JOptionPane.INFORMATION_MESSAGE)
}
})
back.addActionListener(new ActionListener {
def actionPerformed(e: ActionEvent): Unit = layoutCards.show(rootPanel, "LOGIN")
})
center.add(play)
center.add(how)
center.add(back)
menuPanel.add(top, BorderLayout.NORTH)
menuPanel.add(center, BorderLayout.CENTER)
val footer = new JLabel("RESCUE THE CITY. RESTORE THE NEON CORE.", SwingConstants.CENTER)
footer.setForeground(new Color(130, 160, 205))
footer.setBorder(BorderFactory.createEmptyBorder(10, 10, 28, 10))
menuPanel.add(footer, BorderLayout.SOUTH)
}
private def showMenu(): Unit = {
gamePanel.stopGame()
layoutCards.show(rootPanel, "MENU")
}
}
case class NeonCore(var x: Double, var y: Double, var collected: Boolean)
case class CityCitizen(var x: Double, var y: Double, var status: Int, val id: Int)
case class RogueDrone(var x: Double, var y: Double, var stunned: Int, var phase: Double)
class NeonCityGamePanel(backAction: Runnable) extends JPanel with ActionListener with KeyListener {
private val rng = new Random()
private val timer = new Timer(16, this)
private val heldKeys = scala.collection.mutable.Set[Int]()
private val cores = ArrayBuffer[NeonCore]()
private val citizens = ArrayBuffer[CityCitizen]()
private val drones = ArrayBuffer[RogueDrone]()
private var userName = "PLAYER"
private var playerX = 100.0
private var playerY = 520.0
private var playerHealth = 100
private var energy = 100
private var credits = 0
private var rescuedTotal = 0
private var level = 1
private var tickCount = 0
private var dashTicks = 0
private var dashCooldown = 0
private var pulseFlash = 0
private var damageCooldown = 0
private var gamePaused = false
private var finished = false
private var carrying = 0
private var message = "COLLECT NEON CORES AND RESCUE CITY CITIZENS"
private val baseX = 92.0
private val baseY = 530.0
private val gateX = 900.0
private val gateY = 92.0
private var worldName = "NEON DOWNTOWN"
setPreferredSize(new Dimension(960, 620))
setBackground(new Color(7, 10, 28))
setFocusable(true)
addKeyListener(this)
def setPlayerName(value: String): Unit = { userName = value }
def startGame(): Unit = { if (!timer.isRunning) timer.start(); requestFocusInWindow() }
def stopGame(): Unit = { if (timer.isRunning) timer.stop() }
def resetGame(): Unit = {
playerX = baseX
playerY = baseY
playerHealth = 100
energy = 100
credits = 0
rescuedTotal = 0
level = 1
tickCount = 0
dashTicks = 0
dashCooldown = 0
pulseFlash = 0
damageCooldown = 0
gamePaused = false
finished = false
carrying = 0
heldKeys.clear()
setupLevel()
message = "WELCOME TO NEON CITY, " + userName.toUpperCase
repaint()
}
private def setupLevel(): Unit = {
cores.clear()
citizens.clear()
drones.clear()
worldName = level match {
case 1 => "NEON DOWNTOWN"
case 2 => "SKYBRIDGE DISTRICT"
case 3 => "HOLOGRAM GARDENS"
case 4 => "REACTOR QUARTER"
case _ => "THE NEON CORE"
}
var i = 0
while (i < 4 + level) {
val x = 180 + rng.nextInt(690)
val y = 125 + rng.nextInt(410)
cores += NeonCore(x.toDouble, y.toDouble, false)
i += 1
}
i = 0
while (i < 2 + (level / 2)) {
val x = 240 + rng.nextInt(600)
val y = 150 + rng.nextInt(350)
citizens += CityCitizen(x.toDouble, y.toDouble, 0, i)
i += 1
}
i = 0
while (i < 1 + level) {
val x = 260 + rng.nextInt(600)
val y = 150 + rng.nextInt(360)
drones += RogueDrone(x.toDouble, y.toDouble, 0, rng.nextDouble() * 6.28)
i += 1
}
playerX = baseX
playerY = baseY
carrying = 0
playerHealth = 100
energy = 100
message = "DISTRICT " + level + " : COLLECT " + cores.size + " CORES AND RESCUE " + citizens.size + " CITIZENS"
}
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 collectedCoreCount: Int = cores.count(_.collected)
private def savedCitizenCount: Int = citizens.count(_.status == 2)
private def requiredCores: Int = cores.size
private def requiredCitizens: Int = citizens.size
private def tryInteract(): Unit = {
if (finished || gamePaused) return
if (distance(playerX, playerY, baseX, baseY) < 76 && carrying > 0) {
val delivered = carrying
carrying = 0
rescuedTotal += delivered
credits += delivered * 50
var n = 0
while (n < citizens.length) {
if (citizens(n).status == 1) citizens(n).status = 2
n += 1
}
message = "CITIZENS DELIVERED! +" + (delivered * 50) + " CREDITS"
return
}
var nearest: CityCitizen = null
var nearestDistance = 55.0
var i = 0
while (i < citizens.length) {
val c = citizens(i)
val d = distance(playerX, playerY, c.x, c.y)
if (c.status == 0 && d < nearestDistance) { nearest = c; nearestDistance = d }
i += 1
}
if (nearest != null) {
nearest.status = 1
carrying += 1
message = "CITIZEN RESCUED - RETURN TO YOUR BASE"
return
}
if (distance(playerX, playerY, gateX, gateY) < 72) {
if (collectedCoreCount >= requiredCores && savedCitizenCount >= requiredCitizens) {
if (level >= 5) {
finished = true
message = "NEON CORE RESTORED! YOU SAVED THE CITY!"
} else {
level += 1
setupLevel()
}
} else {
message = "GATE LOCKED: COLLECT ALL CORES AND DELIVER ALL CITIZENS"
}
}
}
private def pulseTag(): Unit = {
if (energy < 18 || gamePaused || finished) { message = "NOT ENOUGH ENERGY FOR PULSE TAG"; return }
energy -= 18
pulseFlash = 18
var stunned = 0
var i = 0
while (i < drones.length) {
if (distance(playerX, playerY, drones(i).x, drones(i).y) < 155) {
drones(i).stunned = 150
stunned += 1
}
i += 1
}
message = if (stunned > 0) "PULSE TAG! " + stunned + " DRONE(S) PAUSED" else "PULSE TAG SENT - NO DRONES IN RANGE"
}
private def dash(): Unit = {
if (dashCooldown == 0 && energy >= 10 && !gamePaused && !finished) {
dashTicks = 9
dashCooldown = 55
energy -= 10
}
}
def actionPerformed(e: ActionEvent): Unit = {
if (!gamePaused && !finished) updateWorld()
repaint()
}
private def updateWorld(): Unit = {
tickCount += 1
if (dashCooldown > 0) dashCooldown -= 1
if (dashTicks > 0) dashTicks -= 1
if (pulseFlash > 0) pulseFlash -= 1
if (damageCooldown > 0) damageCooldown -= 1
if (energy < 100 && tickCount % 8 == 0) energy += 1
var moveSpeed = 2.65 + math.min(1.8, collectedCoreCount * 0.18)
if (dashTicks > 0) moveSpeed *= 2.8
if (heldKeys.contains(KeyEvent.VK_W) || heldKeys.contains(KeyEvent.VK_UP)) playerY -= moveSpeed
if (heldKeys.contains(KeyEvent.VK_S) || heldKeys.contains(KeyEvent.VK_DOWN)) playerY += moveSpeed
if (heldKeys.contains(KeyEvent.VK_A) || heldKeys.contains(KeyEvent.VK_LEFT)) playerX -= moveSpeed
if (heldKeys.contains(KeyEvent.VK_D) || heldKeys.contains(KeyEvent.VK_RIGHT)) playerX += moveSpeed
playerX = math.max(35.0, math.min(925.0, playerX))
playerY = math.max(90.0, math.min(580.0, playerY))
var i = 0
while (i < cores.length) {
val core = cores(i)
if (!core.collected && distance(playerX, playerY, core.x, core.y) < 25) {
core.collected = true
credits += 20
energy = math.min(100, energy + 12)
message = "NEON CORE COLLECTED! +20 CREDITS"
}
i += 1
}
i = 0
while (i < citizens.length) {
val c = citizens(i)
if (c.status == 1) {
c.x = playerX - 23.0 - (i % 3) * 13.0
c.y = playerY + 20.0 + (i % 2) * 12.0
}
i += 1
}
i = 0
while (i < drones.length) {
val d = drones(i)
if (d.stunned > 0) d.stunned -= 1
else {
val dx = playerX - d.x
val dy = playerY - d.y
val len = math.max(1.0, math.sqrt(dx * dx + dy * dy))
val droneSpeed = 0.62 + level * 0.12
d.x += dx / len * droneSpeed
d.y += dy / len * droneSpeed
}
d.phase += 0.08
if (d.stunned == 0 && distance(playerX, playerY, d.x, d.y) < 26 && damageCooldown == 0) {
playerHealth -= 8
damageCooldown = 45
message = "DRONE TAGGED YOU! USE F TO PULSE TAG"
if (playerHealth <= 0) {
playerHealth = 100
playerX = baseX
playerY = baseY
carrying = 0
for (citizen <- citizens if citizen.status == 1) citizen.status = 0
message = "REBOOTED AT BASE - YOUR CARRIED CITIZENS WERE LOST"
}
}
i += 1
}
}
def keyTyped(e: KeyEvent): Unit = {}
def keyPressed(e: KeyEvent): Unit = {
val code = e.getKeyCode
heldKeys += code
if (code == KeyEvent.VK_SPACE) dash()
if (code == KeyEvent.VK_E) tryInteract()
if (code == KeyEvent.VK_F) pulseTag()
if (code == KeyEvent.VK_P) gamePaused = !gamePaused
if (code == KeyEvent.VK_B) backAction.run()
if (code == KeyEvent.VK_R && finished) resetGame()
}
def keyReleased(e: KeyEvent): Unit = { heldKeys -= e.getKeyCode }
override def paintComponent(g: Graphics): Unit = {
super.paintComponent(g)
val g2 = g.create().asInstanceOf[Graphics2D]
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON)
drawWorld(g2)
g2.dispose()
}
private def drawWorld(g: Graphics2D): Unit = {
val w = getWidth
val h = getHeight
g.setPaint(new GradientPaint(0, 0, new Color(7, 10, 33), 0, h, new Color(18, 28, 66)))
g.fillRect(0, 0, w, h)
var b = 0
while (b < 15) {
val bx = b * 72 - 8
val bh = 90 + (b * 37 % 135)
g.setColor(new Color(13, 24, 56))
g.fillRoundRect(bx, 100 + (220 - bh), 58, bh + 220, 8, 8)
g.setColor(new Color(32, 80, 115, 150))
var wy = 130
while (wy < 530) {
var wx = bx + 10
while (wx < bx + 52) {
if ((wx + wy + b) % 3 != 0) g.fillRect(wx, wy, 4, 7)
wx += 15
}
wy += 25
}
b += 1
}
g.setColor(new Color(16, 33, 62))
g.fillRect(0, 560, w, 60)
g.setColor(new Color(34, 190, 205, 90))
var gridX = 0
while (gridX < w) { g.drawLine(gridX, 560, gridX - 120, h); gridX += 48 }
var gridY = 570
while (gridY < h) { g.drawLine(0, gridY, w, gridY); gridY += 16 }
// Safe base and exit gate
g.setColor(new Color(20, 220, 190, 55))
g.fillOval((baseX - 43).toInt, (baseY - 43).toInt, 86, 86)
g.setColor(new Color(80, 255, 224))
g.setStroke(new BasicStroke(3f))
g.drawOval((baseX - 31).toInt, (baseY - 31).toInt, 62, 62)
g.setFont(new Font("SansSerif", Font.BOLD, 11))
g.drawString("RESCUE BASE", (baseX - 39).toInt, (baseY + 53).toInt)
val gateColor = if (collectedCoreCount >= requiredCores && savedCitizenCount >= requiredCitizens) new Color(255, 220, 90) else new Color(120, 110, 210)
g.setColor(new Color(gateColor.getRed, gateColor.getGreen, gateColor.getBlue, 55))
g.fillOval((gateX - 42).toInt, (gateY - 42).toInt, 84, 84)
g.setColor(gateColor)
g.setStroke(new BasicStroke(4f))
g.drawOval((gateX - 29).toInt, (gateY - 29).toInt, 58, 58)
g.drawArc((gateX - 20).toInt, (gateY - 20).toInt, 40, 40, 0, 270)
g.drawString("EXIT GATE", (gateX - 32).toInt, (gateY + 54).toInt)
for (core <- cores if !core.collected) {
val pulse = (math.sin(tickCount * 0.09 + core.x) * 3).toInt
g.setColor(new Color(80, 255, 240, 70))
g.fillOval((core.x - 15 - pulse).toInt, (core.y - 15 - pulse).toInt, 30 + pulse * 2, 30 + pulse * 2)
g.setColor(new Color(90, 255, 245))
val x = core.x.toInt
val y = core.y.toInt
val poly = new java.awt.Polygon(Array(x, x + 9, x + 4, x - 6, x - 10), Array(y - 12, y - 2, y + 12, y + 8, y - 4), 5)
g.fillPolygon(poly)
}
for (citizen <- citizens if citizen.status != 2) {
g.setColor(if (citizen.status == 1) new Color(255, 218, 110) else new Color(120, 210, 255))
g.fillOval((citizen.x - 8).toInt, (citizen.y - 15).toInt, 16, 16)
g.fillRoundRect((citizen.x - 7).toInt, (citizen.y).toInt, 14, 19, 8, 8)
if (citizen.status == 0) {
g.setColor(Color.WHITE)
g.drawString("!", (citizen.x - 3).toInt, (citizen.y - 21).toInt)
}
}
for (drone <- drones) {
val dColor = if (drone.stunned > 0) new Color(120, 255, 255) else new Color(255, 90, 160)
g.setColor(new Color(dColor.getRed, dColor.getGreen, dColor.getBlue, 55))
g.fillOval((drone.x - 20).toInt, (drone.y - 20).toInt, 40, 40)
g.setColor(dColor)
g.fillOval((drone.x - 9).toInt, (drone.y - 9).toInt, 18, 18)
g.setColor(new Color(8, 12, 35))
g.fillOval((drone.x - 3).toInt, (drone.y - 3).toInt, 6, 6)
if (drone.stunned > 0) {
g.setColor(Color.WHITE)
g.drawString("Z", (drone.x + 10).toInt, (drone.y - 10).toInt)
}
}
// Player avatar
val playerGlow = if (dashTicks > 0) new Color(255, 255, 150, 100) else new Color(50, 255, 240, 65)
g.setColor(playerGlow)
g.fillOval((playerX - 26).toInt, (playerY - 26).toInt, 52, 52)
g.setColor(new Color(90, 255, 230))
g.fillRoundRect((playerX - 11).toInt, (playerY - 15).toInt, 22, 30, 10, 10)
g.setColor(new Color(235, 255, 255))
g.fillOval((playerX - 7).toInt, (playerY - 22).toInt, 14, 14)
g.setColor(new Color(9, 30, 55))
g.drawString(userName.take(12), (playerX - 28).toInt, (playerY - 30).toInt)
if (pulseFlash > 0) {
g.setColor(new Color(80, 245, 255, 100))
g.setStroke(new BasicStroke(4f))
val radius = (18 - pulseFlash) * 8 + 20
g.drawOval((playerX - radius).toInt, (playerY - radius).toInt, radius * 2, radius * 2)
}
// HUD
g.setColor(new Color(5, 10, 28, 225))
g.fillRoundRect(12, 12, w - 24, 68, 18, 18)
g.setColor(new Color(82, 245, 230))
g.setFont(new Font("SansSerif", Font.BOLD, 17))
g.drawString("NEON FUTURE UPRISING", 28, 38)
g.setFont(new Font("SansSerif", Font.PLAIN, 13))
g.setColor(Color.WHITE)
g.drawString("DISTRICT " + level + "/5 - " + worldName, 29, 61)
g.drawString("CORES " + collectedCoreCount + "/" + requiredCores, 310, 36)
g.drawString("SAVED " + savedCitizenCount + "/" + requiredCitizens + " CARRYING " + carrying, 310, 59)
g.drawString("CREDITS " + credits, 540, 36)
g.drawString("HP " + playerHealth + " ENERGY " + energy, 540, 59)
g.setColor(new Color(80, 255, 220))
g.fillRoundRect(750, 27, 165, 12, 8, 8)
g.setColor(new Color(255, 110, 150))
g.fillRoundRect(750, 48, 165, 8, 8, 8)
g.setColor(Color.WHITE)
g.drawString("E: INTERACT F: PULSE SPACE: DASH B: MENU", 20, h - 14)
g.setColor(new Color(6, 10, 25, 210))
g.fillRoundRect(220, h - 53, 520, 30, 12, 12)
g.setColor(new Color(255, 230, 130))
g.setFont(new Font("SansSerif", Font.BOLD, 12))
g.drawString(message, 235, h - 33)
if (gamePaused || finished) {
g.setColor(new Color(4, 7, 20, 195))
g.fillRect(0, 0, w, h)
g.setFont(new Font("SansSerif", Font.BOLD, 34))
g.setColor(if (finished) new Color(100, 255, 205) else Color.WHITE)
val text = if (finished) "NEON CITY RESTORED!" else "GAME PAUSED"
val metrics = g.getFontMetrics
g.drawString(text, (w - metrics.stringWidth(text)) / 2, h / 2 - 12)
g.setFont(new Font("SansSerif", Font.PLAIN, 16))
g.setColor(Color.WHITE)
val sub = if (finished) "PRESS R TO PLAY AGAIN | PRESS B FOR MENU" else "PRESS P TO RESUME | PRESS B FOR MENU"
g.drawString(sub, (w - g.getFontMetrics.stringWidth(sub)) / 2, h / 2 + 28)
}
}
}
NeonFutureUprisingEvent4.main(Array[String]())