Code Sketch
Bixuu spring season 10
Category: Programming
import java.awt.BorderLayout
import java.awt.CardLayout
import java.awt.Color
import java.awt.Dimension
import java.awt.Font
import java.awt.GradientPaint
import java.awt.Graphics
import java.awt.Graphics2D
import java.awt.RenderingHints
import java.awt.event.ActionEvent
import java.awt.event.ActionListener
import java.awt.event.KeyEvent
import java.awt.event.MouseAdapter
import java.awt.event.MouseEvent
import java.awt.event.WindowAdapter
import java.awt.event.WindowEvent
import java.awt.geom.Ellipse2D
import javax.swing.AbstractAction
import javax.swing.BorderFactory
import javax.swing.JButton
import javax.swing.JComponent
import javax.swing.JFrame
import javax.swing.JLabel
import javax.swing.JPanel
import javax.swing.JTextField
import javax.swing.KeyStroke
import javax.swing.SwingConstants
import javax.swing.SwingUtilities
import javax.swing.Timer
import javax.swing.WindowConstants
import java.util.Random
import scala.collection.mutable.ArrayBuffer
import scala.collection.mutable.HashSet
object BlackMarketDealerEvent10 {
def main(args: Array[String]): Unit = {
SwingUtilities.invokeLater(new Runnable {
override def run(): Unit = {
val app = new BlackMarketDealerFrame()
app.setVisible(true)
app.startLoop()
}
})
}
}
case class DealerOffer(name: String, price: Int, detail: String, kind: Int)
class DealerDrone(var x: Double, var y: Double, val speed: Double) {
var stunnedTicks: Int = 0
}
class BlackMarketState {
var playerName: String = "TRADER"
var credits: Int = 250
var xCrystals: Int = 0
var shadowKeys: Int = 0
var pulseCharges: Int = 2
var reputation: Int = 0
var energy: Int = 3
var speedBoots: Boolean = false
var shieldCharm: Boolean = false
var inEscape: Boolean = false
var paused: Boolean = false
var won: Boolean = false
var gameOver: Boolean = false
var tick: Int = 0
var hitCooldown: Int = 0
var pulseCooldown: Int = 0
var shieldTicks: Int = 0
var pulseEffectTicks: Int = 0
var creditsEarned: Int = 0
var offerSeconds: Int = 30
var offerTick: Int = 0
var offerIndex: Int = 0
var playerX: Double = 115.0
var playerY: Double = 315.0
var targetX: Double = 115.0
var targetY: Double = 315.0
var hasTarget: Boolean = false
val pressedKeys = HashSet[Int]()
val inventory = ArrayBuffer[String]()
val drones = ArrayBuffer[DealerDrone]()
}
class BlackMarketCanvas(val marketData: BlackMarketState) extends JPanel {
private val random = new Random(10L)
private val stars = Array.tabulate(90) { i =>
(random.nextInt(960), random.nextInt(600), 1 + random.nextInt(3))
}
setPreferredSize(new Dimension(960, 600))
setMinimumSize(new Dimension(760, 480))
setFocusable(true)
setBackground(new Color(9, 10, 27))
addMouseListener(new MouseAdapter {
override def mousePressed(e: MouseEvent): Unit = {
if (marketData.inEscape && !marketData.paused && !marketData.won && !marketData.gameOver) {
marketData.targetX = e.getX.toDouble
marketData.targetY = e.getY.toDouble
marketData.hasTarget = true
}
}
})
private def text(g: Graphics2D, value: String, x: Int, y: Int, size: Int, color: Color): Unit = {
g.setFont(new Font("SansSerif", Font.BOLD, size))
g.setColor(color)
g.drawString(value, x, y)
}
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.setPaint(new GradientPaint(0, 0, new Color(8, 12, 31), 0, getHeight, new Color(52, 24, 66)))
g.fillRect(0, 0, getWidth, getHeight)
var i = 0
while (i < stars.length) {
val s = stars(i)
val alpha = 125 + ((math.sin(marketData.tick * 0.035 + i) + 1.0) * 55.0).toInt
g.setColor(new Color(210, 220, 255, alpha))
g.fillOval(s._1, s._2, s._3, s._3)
i += 1
}
g.setColor(new Color(25, 29, 54))
g.fillRoundRect(25, 70, 910, 485, 35, 35)
g.setColor(new Color(95, 68, 116))
g.drawRoundRect(25, 70, 910, 485, 35, 35)
// Market stalls and the exit gate.
g.setColor(new Color(82, 45, 102))
g.fillRoundRect(650, 110, 210, 110, 18, 18)
g.setColor(new Color(255, 185, 91))
g.fillRect(670, 125, 170, 12)
text(g, "DEALER'S STALL", 690, 160, 18, new Color(255, 224, 166))
text(g, "EXIT GATE", 785, 520, 15, new Color(123, 238, 204))
g.setColor(new Color(38, 120, 105))
g.fillRoundRect(770, 530, 150, 18, 10, 10)
g.setColor(new Color(113, 237, 197))
g.drawRoundRect(770, 472, 150, 75, 15, 15)
// Floor tiles.
g.setColor(new Color(71, 70, 105, 90))
var x = 45
while (x < 930) {
g.drawLine(x, 80, x, 548)
x += 45
}
var y = 90
while (y < 555) {
g.drawLine(35, y, 925, y)
y += 45
}
text(g, "BLACK MARKET DISTRICT", 48, 45, 21, new Color(255, 210, 143))
text(g, "PLAYER: " + marketData.playerName, 48, 585, 13, new Color(215, 222, 247))
text(g, "CREDITS " + marketData.credits + " X-CRYSTALS " + marketData.xCrystals + " ENERGY " + marketData.energy, 510, 45, 15, new Color(105, 234, 206))
// Dealer character.
g.setColor(new Color(255, 197, 112, 70))
g.fillOval(725, 173, 65, 65)
g.setColor(new Color(215, 157, 95))
g.fillOval(741, 183, 34, 34)
g.setColor(new Color(36, 26, 48))
g.fillRect(735, 212, 47, 37)
text(g, "SLICK DEALER", 700, 265, 13, new Color(255, 198, 126))
// Player.
if (marketData.shieldTicks > 0) {
g.setColor(new Color(72, 210, 255, 90))
g.fill(new Ellipse2D.Double(marketData.playerX - 28, marketData.playerY - 28, 56, 56))
g.setColor(new Color(105, 228, 255))
g.draw(new Ellipse2D.Double(marketData.playerX - 28, marketData.playerY - 28, 56, 56))
}
g.setColor(new Color(75, 226, 192))
g.fillOval((marketData.playerX - 15).toInt, (marketData.playerY - 15).toInt, 30, 30)
g.setColor(new Color(15, 38, 48))
g.fillOval((marketData.playerX - 6).toInt, (marketData.playerY - 4).toInt, 5, 5)
g.fillOval((marketData.playerX + 3).toInt, (marketData.playerY - 4).toInt, 5, 5)
// Security drones are cartoon floating sentries, not realistic weapons.
i = 0
while (i < marketData.drones.length) {
val d = marketData.drones(i)
val droneColor = if (d.stunnedTicks > 0) new Color(105, 226, 255) else new Color(255, 113, 139)
g.setColor(new Color(droneColor.getRed, droneColor.getGreen, droneColor.getBlue, 65))
g.fillOval((d.x - 25).toInt, (d.y - 25).toInt, 50, 50)
g.setColor(droneColor)
g.fillOval((d.x - 13).toInt, (d.y - 13).toInt, 26, 26)
g.setColor(new Color(30, 24, 48))
g.fillOval((d.x - 5).toInt, (d.y - 4).toInt, 4, 4)
g.fillOval((d.x + 2).toInt, (d.y - 4).toInt, 4, 4)
i += 1
}
if (marketData.pulseEffectTicks > 0) {
val r = (22 - marketData.pulseEffectTicks) * 7 + 24
g.setColor(new Color(103, 226, 255, 135))
g.drawOval((marketData.playerX - r).toInt, (marketData.playerY - r).toInt, r * 2, r * 2)
}
if (marketData.hasTarget && marketData.inEscape) {
g.setColor(new Color(255, 255, 255, 150))
g.drawOval((marketData.targetX - 8).toInt, (marketData.targetY - 8).toInt, 16, 16)
}
text(g, "WASD / ARROWS or CLICK TO MOVE | SPACE: PULSE TAG | Q: SHIELD | B: MARKET", 48, 570, 12, new Color(222, 224, 242))
if (marketData.paused) {
g.setColor(new Color(0, 0, 0, 185))
g.fillRect(25, 70, 910, 485)
text(g, "PAUSED - PRESS P TO RESUME", 315, 315, 25, new Color(255, 220, 154))
}
if (marketData.won) {
g.setColor(new Color(0, 0, 0, 185))
g.fillRect(25, 70, 910, 485)
text(g, "YOU ESCAPED THE BLACK MARKET!", 245, 280, 27, new Color(123, 244, 202))
text(g, "RETURN TO THE MARKET USING THE BUTTON BELOW.", 270, 320, 16, Color.WHITE)
}
if (marketData.gameOver) {
g.setColor(new Color(0, 0, 0, 190))
g.fillRect(25, 70, 910, 485)
text(g, "ENERGY DEPLETED", 375, 280, 30, new Color(255, 142, 158))
text(g, "TRY AGAIN OR RETURN TO THE MARKET.", 325, 320, 17, Color.WHITE)
}
g.dispose()
}
}
class BlackMarketDealerFrame extends JFrame {
private val marketData = new BlackMarketState()
private val cards = new CardLayout()
private val root = new JPanel(cards)
private val nameField = new JTextField("TRADER", 18)
private val marketInfo = new JLabel("Welcome to the Night Market.")
private val statsLabel = new JLabel("")
private val offerLabel = new JLabel("", SwingConstants.CENTER)
private val inventoryLabel = new JLabel("Inventory: empty")
private val gameCanvas = new BlackMarketCanvas(marketData)
private val random = new Random()
private var currentOffer = DealerOffer("X-Crystal Pack", 60, "Adds 3 X-Crystals", 0)
private var lastOfferIndex = -1
private val offers = Array[DealerOffer](
DealerOffer("X-Crystal Pack", 60, "Adds 3 X-Crystals", 0),
DealerOffer("Shadow Key", 85, "A rare key for locked market crates", 1),
DealerOffer("Speed Boots", 110, "Increases movement speed while escaping", 2),
DealerOffer("Aqua Shield Charm", 95, "Adds a stronger temporary shield", 3),
DealerOffer("Pulse Tag Charges", 75, "Adds 2 non-lethal pulse charges", 4),
DealerOffer("Mystery Relic", 45, "A collectible worth reputation", 5)
)
private val loop = new Timer(33, new ActionListener {
override def actionPerformed(e: ActionEvent): Unit = updateWorld()
})
setTitle("SPRING SEASON EVENT 10 - BLACK MARKET DEALER")
setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE)
setSize(1080, 820)
setMinimumSize(new Dimension(900, 700))
setLocationRelativeTo(null)
buildScreens()
setContentPane(root)
installKeys()
addWindowListener(new WindowAdapter {
override def windowClosed(e: WindowEvent): Unit = loop.stop()
})
def startLoop(): Unit = loop.start()
private def button(label: String, action: => Unit): JButton = {
val b = new JButton(label)
b.setFont(new Font("SansSerif", Font.BOLD, 15))
b.setForeground(Color.WHITE)
b.setBackground(new Color(50, 107, 115))
b.setFocusPainted(false)
b.setBorder(BorderFactory.createEmptyBorder(10, 16, 10, 16))
b.addActionListener(new ActionListener {
override def actionPerformed(e: ActionEvent): Unit = action
})
b
}
private def heading(value: String): JLabel = {
val l = new JLabel(value, SwingConstants.CENTER)
l.setFont(new Font("SansSerif", Font.BOLD, 28))
l.setForeground(new Color(255, 210, 145))
l
}
private def label(value: String, size: Int): JLabel = {
val l = new JLabel(value, SwingConstants.CENTER)
l.setFont(new Font("SansSerif", Font.PLAIN, size))
l.setForeground(new Color(225, 230, 246))
l
}
private def makePanel(): JPanel = {
val p = new JPanel()
p.setBackground(new Color(15, 17, 38))
p.setBorder(BorderFactory.createEmptyBorder(18, 24, 18, 24))
p
}
private def buildScreens(): Unit = {
root.add(buildLogin(), "LOGIN")
root.add(buildMarket(), "MARKET")
root.add(buildEscape(), "ESCAPE")
cards.show(root, "LOGIN")
}
private def buildLogin(): JPanel = {
val p = makePanel()
p.setLayout(new BorderLayout(10, 20))
val top = new JPanel(new BorderLayout())
top.setOpaque(false)
top.add(heading("SPRING SEASON EVENT 10"), BorderLayout.CENTER)
val story = label("BLACK MARKET DEALER", 22)
story.setForeground(new Color(104, 230, 203))
top.add(story, BorderLayout.SOUTH)
p.add(top, BorderLayout.NORTH)
val center = new JPanel()
center.setOpaque(false)
center.setLayout(new javax.swing.BoxLayout(center, javax.swing.BoxLayout.Y_AXIS))
val intro = label("Enter the Night Market, make smart deals, collect X-Crystals and escape the Dealer's security drones.", 16)
intro.setAlignmentX(0.5f)
center.add(intro)
center.add(javax.swing.Box.createVerticalStrut(26))
val nameTitle = label("PLAYER NAME", 16)
nameTitle.setAlignmentX(0.5f)
center.add(nameTitle)
nameField.setMaximumSize(new Dimension(320, 42))
nameField.setFont(new Font("SansSerif", Font.BOLD, 18))
nameField.setHorizontalAlignment(SwingConstants.CENTER)
center.add(nameField)
center.add(javax.swing.Box.createVerticalStrut(22))
val start = button("ENTER THE BLACK MARKET", {
val n = nameField.getText.trim
if (n.length > 0) {
marketData.playerName = n.take(18)
refreshLabels()
cards.show(root, "MARKET")
}
})
start.setAlignmentX(0.5f)
center.add(start)
p.add(center, BorderLayout.CENTER)
p.add(label("Offline Swing game - no account, internet or file changes.", 13), BorderLayout.SOUTH)
p
}
private def buildMarket(): JPanel = {
val p = makePanel()
p.setLayout(new BorderLayout(12, 16))
p.add(heading("SLICK DEALER'S NIGHT MARKET"), BorderLayout.NORTH)
val center = new JPanel()
center.setOpaque(false)
center.setLayout(new javax.swing.BoxLayout(center, javax.swing.BoxLayout.Y_AXIS))
statsLabel.setFont(new Font("SansSerif", Font.BOLD, 17))
statsLabel.setForeground(new Color(111, 238, 205))
statsLabel.setAlignmentX(0.5f)
center.add(statsLabel)
center.add(javax.swing.Box.createVerticalStrut(16))
val dealer = label("DEALER: 'Take a look. Every offer has a price. Choose carefully.'", 16)
dealer.setAlignmentX(0.5f)
center.add(dealer)
center.add(javax.swing.Box.createVerticalStrut(18))
val offerPanel = new JPanel(new BorderLayout(8, 8))
offerPanel.setBackground(new Color(37, 30, 59))
offerPanel.setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createLineBorder(new Color(190, 131, 91), 2),
BorderFactory.createEmptyBorder(18, 18, 18, 18)
))
offerPanel.setMaximumSize(new Dimension(680, 130))
offerLabel.setFont(new Font("SansSerif", Font.BOLD, 20))
offerLabel.setForeground(new Color(255, 217, 153))
offerPanel.add(offerLabel, BorderLayout.CENTER)
center.add(offerPanel)
center.add(javax.swing.Box.createVerticalStrut(18))
val actions = new JPanel(new java.awt.GridLayout(2, 3, 10, 10))
actions.setOpaque(false)
actions.add(button("BUY CURRENT DEAL", { buyOffer() }))
actions.add(button("NEXT RANDOM OFFER", { rotateOffer() }))
actions.add(button("SELL 1 X-CRYSTAL", { sellCrystal() }))
actions.add(button("SELL SHADOW KEY", { sellKey() }))
actions.add(button("VIEW INVENTORY", { showInventory() }))
actions.add(button("REFUSE DEAL / LEAVE", { startEscape() }))
center.add(actions)
center.add(javax.swing.Box.createVerticalStrut(14))
inventoryLabel.setAlignmentX(0.5f)
inventoryLabel.setForeground(new Color(190, 202, 230))
center.add(inventoryLabel)
p.add(center, BorderLayout.CENTER)
val bottom = new JPanel(new BorderLayout())
bottom.setOpaque(false)
marketInfo.setForeground(new Color(255, 188, 141))
bottom.add(marketInfo, BorderLayout.CENTER)
bottom.add(button("EXIT TO LOGIN", { cards.show(root, "LOGIN") }), BorderLayout.EAST)
p.add(bottom, BorderLayout.SOUTH)
p
}
private def buildEscape(): JPanel = {
val p = new JPanel(new BorderLayout(8, 8))
p.setBackground(new Color(8, 10, 26))
p.add(gameCanvas, BorderLayout.CENTER)
val controls = new JPanel(new java.awt.FlowLayout(java.awt.FlowLayout.CENTER, 10, 8))
controls.setBackground(new Color(18, 20, 42))
controls.add(button("PULSE TAG (SPACE)", { pulseTag() }))
controls.add(button("AQUA SHIELD (Q)", { activateShield() }))
controls.add(button("PAUSE (P)", { marketData.paused = !marketData.paused }))
controls.add(button("BACK TO MARKET (B)", { returnToMarket() }))
p.add(controls, BorderLayout.SOUTH)
p
}
private def refreshLabels(): Unit = {
statsLabel.setText("PLAYER: " + marketData.playerName + " CREDITS: " + marketData.credits + " X-CRYSTALS: " + marketData.xCrystals + " REPUTATION: " + marketData.reputation)
offerLabel.setText("CURRENT DEAL: " + currentOffer.name + " | PRICE: " + currentOffer.price + " CREDITS | " + currentOffer.detail)
inventoryLabel.setText("Inventory: " + (if (marketData.inventory.isEmpty) "empty" else marketData.inventory.mkString(", ")) + " | Offer rotates in " + marketData.offerSeconds + "s")
}
private def rotateOffer(): Unit = {
var next = random.nextInt(offers.length)
if (offers.length > 1) {
while (next == lastOfferIndex) next = random.nextInt(offers.length)
}
lastOfferIndex = next
currentOffer = offers(next)
marketData.offerSeconds = 30
marketData.offerTick = 0
marketInfo.setText("A new offer has arrived. Check the price before buying.")
refreshLabels()
}
private def buyOffer(): Unit = {
if (marketData.credits < currentOffer.price) {
marketInfo.setText("Not enough credits for this deal. Sell a collectible or choose a cheaper offer.")
} else {
marketData.credits -= currentOffer.price
currentOffer.kind match {
case 0 =>
marketData.xCrystals += 3
marketData.inventory += "3 X-Crystals"
case 1 =>
marketData.shadowKeys += 1
marketData.inventory += "Shadow Key"
case 2 =>
marketData.speedBoots = true
marketData.inventory += "Speed Boots"
case 3 =>
marketData.shieldCharm = true
marketData.inventory += "Aqua Shield Charm"
case 4 =>
marketData.pulseCharges += 2
marketData.inventory += "2 Pulse Tag Charges"
case _ =>
marketData.reputation += 1
marketData.inventory += "Mystery Relic"
}
marketInfo.setText("Deal completed! " + currentOffer.name + " added to your inventory.")
refreshLabels()
}
}
private def sellCrystal(): Unit = {
if (marketData.xCrystals > 0) {
marketData.xCrystals -= 1
marketData.credits += 25
marketInfo.setText("Sold 1 X-Crystal for 25 credits.")
} else {
marketInfo.setText("You do not have an X-Crystal to sell.")
}
refreshLabels()
}
private def sellKey(): Unit = {
if (marketData.shadowKeys > 0) {
marketData.shadowKeys -= 1
marketData.credits += 45
marketInfo.setText("Sold 1 Shadow Key for 45 credits.")
refreshLabels()
} else {
marketInfo.setText("You do not have a Shadow Key to sell.")
}
}
private def showInventory(): Unit = {
val content = if (marketData.inventory.isEmpty) "Your inventory is empty." else marketData.inventory.mkString("\n")
javax.swing.JOptionPane.showMessageDialog(this, content, "PLAYER INVENTORY", javax.swing.JOptionPane.INFORMATION_MESSAGE)
}
private def startEscape(): Unit = {
marketData.inEscape = true
marketData.paused = false
marketData.won = false
marketData.gameOver = false
marketData.energy = 3
marketData.playerX = 115.0
marketData.playerY = 315.0
marketData.targetX = marketData.playerX
marketData.targetY = marketData.playerY
marketData.hasTarget = false
marketData.drones.clear()
marketData.drones += new DealerDrone(820.0, 140.0, 1.25)
marketData.drones += new DealerDrone(860.0, 470.0, 1.15)
if (marketData.reputation >= 2) marketData.drones += new DealerDrone(860.0, 310.0, 1.05)
marketData.hitCooldown = 50
marketData.pulseCooldown = 0
marketData.shieldTicks = 0
marketData.pulseEffectTicks = 0
cards.show(root, "ESCAPE")
gameCanvas.requestFocusInWindow()
marketInfo.setText("Security drones are active! Reach the glowing exit gate or pulse-tag them to stun.")
}
private def returnToMarket(): Unit = {
if (marketData.won) {
marketData.credits += 50
marketData.creditsEarned += 50
marketData.reputation += 1
marketInfo.setText("Escape bonus: +50 credits and +1 reputation. The Dealer has new offers.")
rotateOffer()
} else if (marketData.gameOver) {
marketInfo.setText("You ran out of energy. The Dealer lets you return to the market.")
} else {
marketInfo.setText("You returned to the market before finishing the escape challenge.")
}
marketData.inEscape = false
marketData.paused = false
cards.show(root, "MARKET")
refreshLabels()
}
private def installKeys(): Unit = {
bindKey(KeyEvent.VK_W, "moveUp", true)
bindKey(KeyEvent.VK_W, "stopUp", false)
bindKey(KeyEvent.VK_UP, "moveUpArrow", true)
bindKey(KeyEvent.VK_UP, "stopUpArrow", false)
bindKey(KeyEvent.VK_S, "moveDown", true)
bindKey(KeyEvent.VK_S, "stopDown", false)
bindKey(KeyEvent.VK_DOWN, "moveDownArrow", true)
bindKey(KeyEvent.VK_DOWN, "stopDownArrow", false)
bindKey(KeyEvent.VK_A, "moveLeft", true)
bindKey(KeyEvent.VK_A, "stopLeft", false)
bindKey(KeyEvent.VK_LEFT, "moveLeftArrow", true)
bindKey(KeyEvent.VK_LEFT, "stopLeftArrow", false)
bindKey(KeyEvent.VK_D, "moveRight", true)
bindKey(KeyEvent.VK_D, "stopRight", false)
bindKey(KeyEvent.VK_RIGHT, "moveRightArrow", true)
bindKey(KeyEvent.VK_RIGHT, "stopRightArrow", false)
bindActionKey(KeyEvent.VK_SPACE, "pulse", { pulseTag() })
bindActionKey(KeyEvent.VK_Q, "shield", { activateShield() })
bindActionKey(KeyEvent.VK_P, "pause", { marketData.paused = !marketData.paused })
bindActionKey(KeyEvent.VK_B, "back", { returnToMarket() })
}
private def bindKey(code: Int, name: String, isDown: Boolean): Unit = {
val stroke = KeyStroke.getKeyStroke(code, 0, !isDown)
val id = name
gameCanvas.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(stroke, id)
gameCanvas.getActionMap.put(id, new AbstractAction {
override def actionPerformed(e: ActionEvent): Unit = {
if (isDown) marketData.pressedKeys.add(code) else marketData.pressedKeys.remove(code)
}
})
}
private def bindActionKey(code: Int, name: String, action: => Unit): Unit = {
val stroke = KeyStroke.getKeyStroke(code, 0, false)
gameCanvas.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(stroke, name)
gameCanvas.getActionMap.put(name, new AbstractAction {
override def actionPerformed(e: ActionEvent): Unit = action
})
}
private def pulseTag(): Unit = {
if (marketData.inEscape && !marketData.paused && !marketData.won && !marketData.gameOver && marketData.pulseCooldown <= 0 && marketData.pulseCharges > 0) {
marketData.pulseCharges -= 1
marketData.pulseCooldown = 55
marketData.pulseEffectTicks = 22
var i = 0
while (i < marketData.drones.length) {
val d = marketData.drones(i)
val dx = d.x - marketData.playerX
val dy = d.y - marketData.playerY
if (math.sqrt(dx * dx + dy * dy) < 170.0) d.stunnedTicks = 100
i += 1
}
}
}
private def activateShield(): Unit = {
if (marketData.inEscape && !marketData.paused && !marketData.won && !marketData.gameOver) {
if (marketData.shieldCharm || marketData.shieldTicks <= 0) marketData.shieldTicks = 110
}
}
private def updateWorld(): Unit = {
marketData.tick += 1
if (!marketData.inEscape) {
marketData.offerTick += 1
if (marketData.offerTick >= 30) {
marketData.offerTick = 0
if (marketData.offerSeconds > 0) marketData.offerSeconds -= 1
if (marketData.offerSeconds <= 0) rotateOffer()
refreshLabels()
}
} else if (!marketData.paused && !marketData.won && !marketData.gameOver) {
updateEscape()
}
if (marketData.pulseEffectTicks > 0) marketData.pulseEffectTicks -= 1
gameCanvas.repaint()
}
private def updateEscape(): Unit = {
val baseSpeed = if (marketData.speedBoots) 4.4 else 3.2
val crystalBoost = math.min(1.5, marketData.xCrystals * 0.12)
val moveSpeed = baseSpeed + crystalBoost
var dx = 0.0
var dy = 0.0
if (marketData.pressedKeys.contains(KeyEvent.VK_W) || marketData.pressedKeys.contains(KeyEvent.VK_UP)) dy -= 1.0
if (marketData.pressedKeys.contains(KeyEvent.VK_S) || marketData.pressedKeys.contains(KeyEvent.VK_DOWN)) dy += 1.0
if (marketData.pressedKeys.contains(KeyEvent.VK_A) || marketData.pressedKeys.contains(KeyEvent.VK_LEFT)) dx -= 1.0
if (marketData.pressedKeys.contains(KeyEvent.VK_D) || marketData.pressedKeys.contains(KeyEvent.VK_RIGHT)) dx += 1.0
if (dx != 0.0 || dy != 0.0) {
val length = math.sqrt(dx * dx + dy * dy)
marketData.playerX += (dx / length) * moveSpeed
marketData.playerY += (dy / length) * moveSpeed
marketData.hasTarget = false
} else if (marketData.hasTarget) {
val tx = marketData.targetX - marketData.playerX
val ty = marketData.targetY - marketData.playerY
val distance = math.sqrt(tx * tx + ty * ty)
if (distance < moveSpeed) marketData.hasTarget = false
else {
marketData.playerX += (tx / distance) * moveSpeed
marketData.playerY += (ty / distance) * moveSpeed
}
}
marketData.playerX = math.max(48.0, math.min(920.0, marketData.playerX))
marketData.playerY = math.max(85.0, math.min(540.0, marketData.playerY))
if (marketData.hitCooldown > 0) marketData.hitCooldown -= 1
if (marketData.pulseCooldown > 0) marketData.pulseCooldown -= 1
if (marketData.shieldTicks > 0) marketData.shieldTicks -= 1
var i = 0
while (i < marketData.drones.length) {
val d = marketData.drones(i)
if (d.stunnedTicks > 0) d.stunnedTicks -= 1
else {
val ex = marketData.playerX - d.x
val ey = marketData.playerY - d.y
val dist = math.sqrt(ex * ex + ey * ey)
if (dist > 0.1) {
d.x += (ex / dist) * d.speed
d.y += (ey / dist) * d.speed
}
if (dist < 29.0 && marketData.hitCooldown <= 0) {
if (marketData.shieldTicks > 0) {
d.stunnedTicks = 50
} else {
marketData.energy -= 1
marketData.hitCooldown = 65
marketData.playerX = math.max(55.0, marketData.playerX - 38.0)
if (marketData.energy <= 0) marketData.gameOver = true
}
}
}
i += 1
}
if (marketData.playerX > 770.0 && marketData.playerY > 470.0) marketData.won = true
}
}
BlackMarketDealerEvent10.main(Array[String]())