Code Sketch
Bixuu MysticPortalExpeditionEvent7
Category: Programming
import java.awt.{BasicStroke, BorderLayout, CardLayout, Color, Dimension, Font, GradientPaint, Graphics, Graphics2D, RenderingHints}
import java.awt.event.{ActionEvent, ActionListener, KeyAdapter, KeyEvent, MouseAdapter, MouseEvent, WindowAdapter, WindowEvent}
import java.awt.geom.Ellipse2D
import javax.swing.{BorderFactory, JButton, JFrame, JLabel, JOptionPane, JPanel, JTextField, SwingConstants, SwingUtilities, Timer, WindowConstants}
import scala.collection.mutable.ArrayBuffer
object MysticPortalExpeditionEvent7 {
private val frameTitle = "INFINITY REALMS SEASON 07 - MYSTIC PORTAL EXPEDITION"
def main(args: Array[String]): Unit = {
SwingUtilities.invokeLater(new Runnable {
def run(): Unit = {
val frame = new JFrame(frameTitle)
frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE)
frame.setSize(1080, 720)
frame.setMinimumSize(new Dimension(900, 620))
frame.setLocationRelativeTo(null)
val cardLayout = new CardLayout()
val root = new JPanel(cardLayout)
root.setBackground(new Color(9, 13, 31))
val loginPanel = new JPanel(new BorderLayout())
loginPanel.setBackground(new Color(12, 17, 42))
loginPanel.setBorder(BorderFactory.createEmptyBorder(35, 70, 35, 70))
val title = new JLabel("MYSTIC PORTAL EXPEDITION", SwingConstants.CENTER)
title.setForeground(new Color(190, 225, 255))
title.setFont(new Font("Dialog", Font.BOLD, 32))
val subtitle = new JLabel("INFINITY REALMS SEASON 07 | EXPLORE THE UNKNOWN", SwingConstants.CENTER)
subtitle.setForeground(new Color(152, 177, 220))
subtitle.setFont(new Font("Dialog", Font.BOLD, 15))
val centre = new JPanel()
centre.setOpaque(false)
centre.setLayout(new javax.swing.BoxLayout(centre, javax.swing.BoxLayout.Y_AXIS))
val story = new JLabel("Three worlds are sealed. Find the runes, awaken the portals, and discover the lost realm.", SwingConstants.CENTER)
story.setForeground(new Color(220, 230, 255))
story.setFont(new Font("Dialog", Font.PLAIN, 15))
story.setAlignmentX(0.5f)
val nameLabel = new JLabel("ENTER YOUR EXPLORER NAME", SwingConstants.CENTER)
nameLabel.setForeground(new Color(150, 230, 220))
nameLabel.setFont(new Font("Dialog", Font.BOLD, 14))
nameLabel.setAlignmentX(0.5f)
val nameField = new JTextField("Explorer")
nameField.setFont(new Font("Dialog", Font.PLAIN, 18))
nameField.setHorizontalAlignment(SwingConstants.CENTER)
nameField.setMaximumSize(new Dimension(330, 42))
nameField.setAlignmentX(0.5f)
nameField.setBackground(new Color(25, 34, 66))
nameField.setForeground(Color.WHITE)
nameField.setCaretColor(Color.WHITE)
nameField.setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createLineBorder(new Color(94, 180, 220), 2),
BorderFactory.createEmptyBorder(7, 12, 7, 12)
))
val startButton = new JButton("START EXPEDITION")
startButton.setFont(new Font("Dialog", Font.BOLD, 17))
startButton.setForeground(Color.WHITE)
startButton.setBackground(new Color(42, 116, 145))
startButton.setFocusPainted(false)
startButton.setAlignmentX(0.5f)
startButton.setMaximumSize(new Dimension(260, 48))
val controls = new JLabel("WASD / ARROWS: MOVE CLICK: WALK E: INTERACT SPACE: MYSTIC DASH Q: AURA", SwingConstants.CENTER)
controls.setForeground(new Color(145, 160, 200))
controls.setFont(new Font("Dialog", Font.PLAIN, 12))
controls.setAlignmentX(0.5f)
centre.add(javax.swing.Box.createVerticalGlue())
centre.add(story)
centre.add(javax.swing.Box.createVerticalStrut(35))
centre.add(nameLabel)
centre.add(javax.swing.Box.createVerticalStrut(10))
centre.add(nameField)
centre.add(javax.swing.Box.createVerticalStrut(22))
centre.add(startButton)
centre.add(javax.swing.Box.createVerticalStrut(35))
centre.add(controls)
centre.add(javax.swing.Box.createVerticalGlue())
val headingPanel = new JPanel(new BorderLayout())
headingPanel.setOpaque(false)
headingPanel.add(title, BorderLayout.CENTER)
headingPanel.add(subtitle, BorderLayout.SOUTH)
loginPanel.add(headingPanel, BorderLayout.NORTH)
loginPanel.add(centre, BorderLayout.CENTER)
root.add(loginPanel, "login")
frame.setContentPane(root)
var currentGame: MysticGamePanel = null
startButton.addActionListener(new ActionListener {
def actionPerformed(e: ActionEvent): Unit = {
val playerName = nameField.getText.trim
if (playerName.length == 0) {
JOptionPane.showMessageDialog(frame, "Please enter your explorer name.", "Explorer Name", JOptionPane.INFORMATION_MESSAGE)
} else {
if (currentGame != null) currentGame.stopGame()
currentGame = new MysticGamePanel(playerName)
root.add(currentGame, "game")
cardLayout.show(root, "game")
currentGame.startGame()
currentGame.requestFocusInWindow()
}
}
})
frame.addWindowListener(new WindowAdapter {
override def windowClosing(e: WindowEvent): Unit = {
if (currentGame != null) currentGame.stopGame()
}
})
frame.setVisible(true)
nameField.requestFocusInWindow()
}
})
}
}
class MysticGamePanel(playerName: String) extends JPanel {
private case class Relic(var x: Int, var y: Int, var collected: Boolean)
private val realmNames = Array("Whispering Grove", "Astral Library", "Crystal Caverns")
private val realmDescriptions = Array(
"Ancient trees hide the first portal runes.",
"Floating books guard the memory seals.",
"The final crystals wait beneath the mountain."
)
private val relics = ArrayBuffer[Relic]()
private var realmIndex = 0
private var explorerX = 105.0
private var explorerY = 345.0
private var moveUp = false
private var moveDown = false
private var moveLeft = false
private var moveRight = false
private var mouseTargetActive = false
private var mouseTargetX = 0.0
private var mouseTargetY = 0.0
private var totalRelics = 0
private var energy = 55
private var dashTicks = 0
private var shieldTicks = 0
private var damageCooldown = 0
private var message = "Find the glowing relics. Bring their energy to the portal."
private var messageTicks = 300
private var hasWon = false
private var tickCount = 0
private var wispOneX = 500.0
private var wispOneY = 210.0
private var wispTwoX = 720.0
private var wispTwoY = 430.0
private val panelWidth = 1080
private val panelHeight = 720
private val portalX = 930.0
private val portalY = 350.0
setPreferredSize(new Dimension(panelWidth, panelHeight))
setFocusable(true)
setDoubleBuffered(true)
setBackground(new Color(10, 16, 38))
private def loadRelics(): Unit = {
relics.clear()
relics += Relic(220, 170, false)
relics += Relic(390, 290, false)
relics += Relic(570, 160, false)
relics += Relic(720, 475, false)
relics += Relic(475, 520, false)
}
loadRelics()
private val gameTimer = new Timer(16, new ActionListener {
def actionPerformed(e: ActionEvent): Unit = updateGame()
})
addKeyListener(new KeyAdapter {
override def keyPressed(e: KeyEvent): Unit = {
e.getKeyCode match {
case KeyEvent.VK_W | KeyEvent.VK_UP => moveUp = true; mouseTargetActive = false
case KeyEvent.VK_S | KeyEvent.VK_DOWN => moveDown = true; mouseTargetActive = false
case KeyEvent.VK_A | KeyEvent.VK_LEFT => moveLeft = true; mouseTargetActive = false
case KeyEvent.VK_D | KeyEvent.VK_RIGHT => moveRight = true; mouseTargetActive = false
case KeyEvent.VK_E => interact()
case KeyEvent.VK_SPACE => useDash()
case KeyEvent.VK_Q => useAura()
case KeyEvent.VK_P => togglePause()
case KeyEvent.VK_B => showExitMessage()
case _ =>
}
}
override def keyReleased(e: KeyEvent): Unit = {
e.getKeyCode match {
case KeyEvent.VK_W | KeyEvent.VK_UP => moveUp = false
case KeyEvent.VK_S | KeyEvent.VK_DOWN => moveDown = false
case KeyEvent.VK_A | KeyEvent.VK_LEFT => moveLeft = false
case KeyEvent.VK_D | KeyEvent.VK_RIGHT => moveRight = false
case _ =>
}
}
})
addMouseListener(new MouseAdapter {
override def mousePressed(e: MouseEvent): Unit = {
if (!hasWon && e.getButton == MouseEvent.BUTTON1) {
mouseTargetX = e.getX.toDouble
mouseTargetY = e.getY.toDouble
mouseTargetActive = true
requestFocusInWindow()
}
}
})
def startGame(): Unit = {
if (!gameTimer.isRunning) gameTimer.start()
requestFocusInWindow()
}
def stopGame(): Unit = {
if (gameTimer.isRunning) gameTimer.stop()
}
private def setMessage(text: String): Unit = {
message = text
messageTicks = 240
}
private def collectedHere: Int = {
var count = 0
var i = 0
while (i < relics.length) {
if (relics(i).collected) count += 1
i += 1
}
count
}
private def movePlayer(dx: Double, dy: Double): Unit = {
val length = math.sqrt(dx * dx + dy * dy)
if (length > 0.001) {
val speedBonus = math.min(1.5, totalRelics.toDouble * 0.08)
val speed = 3.6 + speedBonus
explorerX += (dx / length) * speed
explorerY += (dy / length) * speed
}
explorerX = math.max(55.0, math.min(1015.0, explorerX))
explorerY = math.max(115.0, math.min(655.0, explorerY))
}
private def updateGame(): Unit = {
if (!hasWon) {
tickCount += 1
if (messageTicks > 0) messageTicks -= 1
if (dashTicks > 0) dashTicks -= 1
if (shieldTicks > 0) shieldTicks -= 1
if (damageCooldown > 0) damageCooldown -= 1
var dx = 0.0
var dy = 0.0
if (moveLeft) dx -= 1.0
if (moveRight) dx += 1.0
if (moveUp) dy -= 1.0
if (moveDown) dy += 1.0
if (dx != 0.0 || dy != 0.0) {
mouseTargetActive = false
movePlayer(dx, dy)
} else if (mouseTargetActive) {
val tx = mouseTargetX - explorerX
val ty = mouseTargetY - explorerY
val distance = math.sqrt(tx * tx + ty * ty)
if (distance < 9.0) mouseTargetActive = false
else movePlayer(tx, ty)
}
wispOneX = 500.0 + math.sin(tickCount.toDouble * 0.025) * 115.0
wispOneY = 215.0 + math.cos(tickCount.toDouble * 0.018) * 65.0
wispTwoX = 700.0 + math.cos(tickCount.toDouble * 0.021) * 95.0
wispTwoY = 430.0 + math.sin(tickCount.toDouble * 0.017) * 55.0
if (damageCooldown == 0 && shieldTicks == 0 && (distanceTo(explorerX, explorerY, wispOneX, wispOneY) < 29.0 || distanceTo(explorerX, explorerY, wispTwoX, wispTwoY) < 29.0)) {
energy = math.max(0, energy - 8)
damageCooldown = 65
setMessage("A Shadow Wisp drained your energy! Use Q for an Aura Shield.")
}
repaint()
}
}
private def distanceTo(x1: Double, y1: Double, x2: Double, y2: Double): Double = {
val dx = x1 - x2
val dy = y1 - y2
math.sqrt(dx * dx + dy * dy)
}
private def interact(): Unit = {
if (hasWon) return
var nearestIndex = -1
var nearestDistance = 99999.0
var i = 0
while (i < relics.length) {
val relic = relics(i)
if (!relic.collected) {
val d = distanceTo(explorerX, explorerY, relic.x.toDouble, relic.y.toDouble)
if (d < nearestDistance) {
nearestDistance = d
nearestIndex = i
}
}
i += 1
}
if (nearestIndex >= 0 && nearestDistance < 52.0) {
relics(nearestIndex).collected = true
totalRelics += 1
energy = math.min(100, energy + 18)
setMessage("Relic collected! Energy restored. " + collectedHere.toString + "/5 in this realm.")
} else if (distanceTo(explorerX, explorerY, portalX, portalY) < 82.0) {
if (collectedHere >= 5) {
if (realmIndex < 2) {
realmIndex += 1
explorerX = 105.0
explorerY = 345.0
energy = math.min(100, energy + 25)
loadRelics()
setMessage("Portal opened! Welcome to " + realmNames(realmIndex) + ".")
} else {
hasWon = true
stopGame()
repaint()
JOptionPane.showMessageDialog(this, "The Mystic Nexus is restored!\nExplorer: " + playerName + "\nRelics found: " + totalRelics.toString, "EXPEDITION COMPLETE", JOptionPane.INFORMATION_MESSAGE)
}
} else {
setMessage("The portal is sealed. Collect all 5 relics in this realm first.")
}
} else {
setMessage("Move close to a glowing relic or the portal, then press E.")
}
repaint()
}
private def useDash(): Unit = {
if (hasWon) return
if (energy >= 12 && dashTicks == 0) {
val dx = (if (moveRight) 1.0 else 0.0) - (if (moveLeft) 1.0 else 0.0)
val dy = (if (moveDown) 1.0 else 0.0) - (if (moveUp) 1.0 else 0.0)
var dashX = dx
var dashY = dy
if (dashX == 0.0 && dashY == 0.0 && mouseTargetActive) {
dashX = mouseTargetX - explorerX
dashY = mouseTargetY - explorerY
}
if (dashX == 0.0 && dashY == 0.0) dashX = 1.0
val length = math.sqrt(dashX * dashX + dashY * dashY)
explorerX = math.max(55.0, math.min(1015.0, explorerX + (dashX / length) * 105.0))
explorerY = math.max(115.0, math.min(655.0, explorerY + (dashY / length) * 105.0))
energy -= 12
dashTicks = 22
mouseTargetActive = false
setMessage("MYSTIC DASH!")
} else {
setMessage("Not enough energy for Mystic Dash. Collect relics!")
}
repaint()
}
private def useAura(): Unit = {
if (hasWon) return
if (energy >= 20 && shieldTicks == 0) {
energy -= 20
shieldTicks = 150
setMessage("AURA SHIELD activated!")
} else {
setMessage("Need 20 energy to activate Aura Shield.")
}
repaint()
}
private def togglePause(): Unit = {
if (gameTimer.isRunning) {
gameTimer.stop()
setMessage("Paused. Press P to continue.")
} else if (!hasWon) {
gameTimer.start()
setMessage("Expedition resumed.")
}
repaint()
}
private def showExitMessage(): Unit = {
setMessage("To leave, close this game window. Your laptop files are not changed.")
repaint()
}
private def drawCrystal(g: Graphics2D, x: Int, y: Int, size: Int, color: Color): Unit = {
val xs = Array(x, x + size / 2, x + size, x + size * 3 / 4, x + size / 2, x + size / 4)
val ys = Array(y + size / 2, y, y + size / 2, y + size, y + size * 5 / 4, y + size)
g.setColor(color)
g.fillPolygon(xs, ys, xs.length)
g.setColor(new Color(245, 250, 255, 190))
g.drawLine(x + size / 2, y + 2, x + size / 2, y + size * 5 / 4)
}
private def drawWisp(g: Graphics2D, x: Int, y: Int, color: Color): Unit = {
g.setColor(new Color(color.getRed, color.getGreen, color.getBlue, 55))
g.fillOval(x - 22, y - 22, 44, 44)
g.setColor(color)
g.fillOval(x - 10, y - 10, 20, 20)
g.setColor(new Color(255, 255, 255, 210))
g.fillOval(x - 4, y - 5, 5, 5)
g.fillOval(x + 3, y - 5, 5, 5)
}
override def paintComponent(graphics: Graphics): Unit = {
super.paintComponent(graphics)
val g = graphics.create().asInstanceOf[Graphics2D]
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON)
val width = getWidth
val height = getHeight
val topColor = if (realmIndex == 0) new Color(13, 40, 53) else if (realmIndex == 1) new Color(24, 22, 62) else new Color(29, 24, 57)
val bottomColor = if (realmIndex == 0) new Color(13, 73, 70) else if (realmIndex == 1) new Color(52, 39, 98) else new Color(75, 38, 91)
g.setPaint(new GradientPaint(0, 0, topColor, 0, height, bottomColor))
g.fillRect(0, 0, width, height)
var star = 0
while (star < 65) {
val sx = (star * 173 + 41) % math.max(1, width)
val sy = (star * 97 + 25) % math.max(1, height)
val alpha = 80 + ((star * 23) % 150)
g.setColor(new Color(205, 225, 255, alpha))
g.fillOval(sx, sy, 2 + (star % 3), 2 + (star % 3))
star += 1
}
g.setColor(new Color(255, 255, 255, 18))
var gridX = 35
while (gridX < width) { g.drawLine(gridX, 95, gridX, height); gridX += 55 }
var gridY = 120
while (gridY < height) { g.drawLine(0, gridY, width, gridY); gridY += 55 }
if (realmIndex == 0) {
var tree = 0
while (tree < 9) {
val tx = 45 + tree * 112
g.setColor(new Color(17, 52, 48))
g.fillRect(tx, 150, 18, 365)
g.setColor(new Color(27, 91, 72, 210))
g.fillOval(tx - 33, 115 + (tree % 3) * 22, 85, 85)
tree += 1
}
} else if (realmIndex == 1) {
var book = 0
while (book < 6) {
val bx = 70 + book * 155
g.setColor(new Color(115, 105, 180, 130))
g.fillRoundRect(bx, 150 + (book % 2) * 260, 75, 90, 12, 12)
g.setColor(new Color(220, 205, 255, 150))
g.drawLine(bx + 12, 165 + (book % 2) * 260, bx + 63, 165 + (book % 2) * 260)
book += 1
}
} else {
var rock = 0
while (rock < 8) {
val rx = 35 + rock * 135
val ry = 500 + (rock % 3) * 25
g.setColor(new Color(71, 54, 116, 210))
g.fillPolygon(Array(rx, rx + 34, rx + 75, rx + 52, rx + 10), Array(ry + 55, ry, ry + 32, ry + 70, ry + 75), 5)
rock += 1
}
}
g.setColor(new Color(8, 13, 30, 165))
g.fillRoundRect(0, 0, width, 88, 0, 0)
g.setColor(new Color(220, 235, 255))
g.setFont(new Font("Dialog", Font.BOLD, 19))
g.drawString("MYSTIC PORTAL EXPEDITION", 24, 31)
g.setFont(new Font("Dialog", Font.BOLD, 14))
g.setColor(new Color(155, 220, 245))
g.drawString("Explorer: " + playerName + " | Realm " + (realmIndex + 1).toString + "/3: " + realmNames(realmIndex), 24, 58)
g.setColor(new Color(225, 230, 250))
g.drawString("Relics " + collectedHere.toString + "/5 Total " + totalRelics.toString, 675, 30)
g.setColor(new Color(40, 48, 70))
g.fillRoundRect(675, 43, 180, 15, 8, 8)
g.setColor(new Color(88, 220, 195))
g.fillRoundRect(675, 43, energy * 180 / 100, 15, 8, 8)
g.setColor(Color.WHITE)
g.setFont(new Font("Dialog", Font.PLAIN, 11))
g.drawString("ENERGY " + energy.toString + "/100", 862, 55)
var i = 0
while (i < relics.length) {
val r = relics(i)
if (!r.collected) {
val pulse = (math.sin(tickCount.toDouble * 0.09 + i.toDouble) * 4.0).toInt
g.setColor(new Color(80, 220, 230, 45))
g.fillOval(r.x - 20 - pulse, r.y - 20 - pulse, 48 + pulse * 2, 48 + pulse * 2)
val crystalColor = if (realmIndex == 0) new Color(105, 242, 180) else if (realmIndex == 1) new Color(190, 160, 255) else new Color(120, 215, 255)
drawCrystal(g, r.x - 10, r.y - 13 + pulse / 3, 20, crystalColor)
}
i += 1
}
val portalColor = if (collectedHere >= 5) new Color(255, 215, 110) else new Color(125, 125, 180)
g.setColor(new Color(portalColor.getRed, portalColor.getGreen, portalColor.getBlue, 35))
g.fillOval(portalX.toInt - 58, portalY.toInt - 72, 116, 144)
g.setStroke(new BasicStroke(7.0f))
g.setColor(portalColor)
g.drawOval(portalX.toInt - 34, portalY.toInt - 52, 68, 104)
g.setStroke(new BasicStroke(2.0f))
g.setColor(new Color(240, 240, 255))
g.setFont(new Font("Dialog", Font.BOLD, 12))
g.drawString(if (collectedHere >= 5) "OPEN PORTAL" else "SEALED", portalX.toInt - 37, portalY.toInt + 75)
drawWisp(g, wispOneX.toInt, wispOneY.toInt, new Color(180, 135, 255))
drawWisp(g, wispTwoX.toInt, wispTwoY.toInt, new Color(105, 205, 255))
val px = explorerX.toInt
val py = explorerY.toInt
if (shieldTicks > 0) {
g.setColor(new Color(105, 235, 255, 65))
g.fillOval(px - 28, py - 39, 56, 78)
g.setColor(new Color(135, 245, 255, 205))
g.setStroke(new BasicStroke(3.0f))
g.drawOval(px - 28, py - 39, 56, 78)
g.setStroke(new BasicStroke(1.0f))
}
g.setColor(new Color(8, 12, 28, 170))
g.fillOval(px - 15, py + 18, 30, 10)
g.setColor(new Color(55, 155, 180))
g.fillRoundRect(px - 13, py - 9, 26, 34, 10, 10)
g.setColor(new Color(226, 205, 170))
g.fillOval(px - 10, py - 28, 20, 21)
g.setColor(new Color(235, 245, 255))
g.fillOval(px - 5, py - 21, 3, 3)
g.fillOval(px + 3, py - 21, 3, 3)
if (mouseTargetActive) {
g.setColor(new Color(255, 255, 255, 130))
g.drawOval(mouseTargetX.toInt - 9, mouseTargetY.toInt - 9, 18, 18)
}
g.setColor(new Color(7, 10, 25, 190))
g.fillRoundRect(18, height - 72, width - 36, 52, 14, 14)
g.setColor(new Color(230, 235, 255))
g.setFont(new Font("Dialog", Font.BOLD, 13))
g.drawString("WASD / ARROWS: MOVE | CLICK: WALK | E: COLLECT / PORTAL | SPACE: DASH | Q: AURA | P: PAUSE", 32, height - 49)
g.setColor(new Color(150, 220, 230))
g.setFont(new Font("Dialog", Font.PLAIN, 12))
g.drawString(if (messageTicks > 0) message else realmDescriptions(realmIndex), 32, height - 29)
if (hasWon) {
g.setColor(new Color(5, 8, 22, 205))
g.fillRect(0, 88, width, height - 160)
g.setColor(new Color(245, 225, 160))
g.setFont(new Font("Dialog", Font.BOLD, 38))
g.drawString("MYSTIC NEXUS RESTORED!", 260, height / 2 - 10)
g.setFont(new Font("Dialog", Font.PLAIN, 18))
g.setColor(Color.WHITE)
g.drawString("All three realms are free. Your expedition is complete.", 285, height / 2 + 28)
}
g.dispose()
}
}
MysticPortalExpeditionEvent7.main(Array[String]())