Code Sketch
yoiiii111
Category: Programming
import java.awt.BasicStroke
import java.awt.BorderLayout
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.MouseAdapter
import java.awt.event.MouseEvent
import java.awt.event.MouseMotionAdapter
import javax.swing.JButton
import javax.swing.JFrame
import javax.swing.JPanel
import javax.swing.SwingUtilities
import javax.swing.Timer
import javax.swing.WindowConstants
import scala.collection.mutable.ArrayBuffer
import scala.util.Random
// ============================================================
// GOKUL ASHTAMI - ULTRA FESTIVAL ANIMATION
// FULL STANDALONE SCALA / SWING VERSION
// ============================================================
// ============================================================
// CONSTANTS
// ============================================================
val SCREEN_W: Int = 1200
val SCREEN_H: Int = 760
val rnd =
new Random()
var running: Boolean =
true
var elapsed: Double =
0.0
var swingAngle: Double =
0.0
var swingDirection: Double =
1.0
var moonPulse: Double =
0.0
var glowPulse: Double =
0.0
var flutePulse: Double =
0.0
var titlePulse: Double =
0.0
var butterCount: Int =
0
// ============================================================
// MUTABLE FLOWER
// ============================================================
class Flower(
var x: Double,
var y: Double,
var vx: Double,
var vy: Double,
var life: Int,
var kind: Int
)
// ============================================================
// MUTABLE SPARK
// ============================================================
class Spark(
var x: Double,
var y: Double,
var vx: Double,
var vy: Double,
var life: Int,
var size: Int
)
// ============================================================
// STAR
// ============================================================
class Star(
var x: Double,
var y: Double,
var size: Double,
var speed: Double,
var phase: Double
)
// ============================================================
// BUTTER PARTICLE
// ============================================================
class ButterParticle(
var x: Double,
var y: Double,
var vx: Double,
var vy: Double,
var life: Int,
var size: Int
)
// ============================================================
// PARTICLE ARRAYS
// ============================================================
val flowers =
ArrayBuffer[Flower]()
val sparks =
ArrayBuffer[Spark]()
val stars =
ArrayBuffer[Star]()
val butterParticles =
ArrayBuffer[ButterParticle]()
// ============================================================
// CREATE STARS
// ============================================================
var starCreateIndex: Int =
0
while (
starCreateIndex < 95
) {
stars +=
new Star(
rnd.nextDouble() * SCREEN_W,
60.0 + rnd.nextDouble() * 390.0,
1.0 + rnd.nextDouble() * 3.0,
0.2 + rnd.nextDouble() * 0.8,
rnd.nextDouble() * 6.28
)
starCreateIndex += 1
}
// ============================================================
// CREATE FLOWER
// ============================================================
def addFlower(
px: Double,
py: Double
): Unit = {
val k: Int =
rnd.nextInt(4)
flowers +=
new Flower(
px,
py,
-1.5 + rnd.nextDouble() * 3.0,
-3.0 - rnd.nextDouble() * 2.5,
90 + rnd.nextInt(90),
k
)
}
// ============================================================
// CREATE SPARK
// ============================================================
def addSpark(
px: Double,
py: Double
): Unit = {
val angle: Double =
rnd.nextDouble() * math.Pi * 2.0
val speed: Double =
0.8 + rnd.nextDouble() * 3.5
sparks +=
new Spark(
px,
py,
math.cos(angle) * speed,
math.sin(angle) * speed,
25 + rnd.nextInt(50),
2 + rnd.nextInt(5)
)
}
// ============================================================
// CREATE BUTTER
// ============================================================
def addButterParticle(
px: Double,
py: Double
): Unit = {
butterParticles +=
new ButterParticle(
px,
py,
-1.0 + rnd.nextDouble() * 2.0,
-3.0 - rnd.nextDouble() * 2.0,
60 + rnd.nextInt(45),
4 + rnd.nextInt(5)
)
}
// ============================================================
// INITIAL FLOWERS
// ============================================================
var flowerIndex: Int =
0
while (
flowerIndex < 18
) {
addFlower(
120 + rnd.nextDouble() * 960,
620 + rnd.nextDouble() * 100
)
flowerIndex += 1
}
// ============================================================
// DRAW UTILS
// ============================================================
def drawGlow(
g: Graphics2D,
cx: Int,
cy: Int,
radius: Int,
alpha: Int
): Unit = {
var r: Int =
radius
while (
r > 10
) {
val a: Int =
math.max(
5,
math.min(
255,
alpha -
(radius - r) / 2
)
)
g.setColor(
new Color(
255,
210,
80,
a
)
)
g.fillOval(
cx - r,
cy - r,
r * 2,
r * 2
)
r -= 12
}
}
// ============================================================
// STAR DRAW
// ============================================================
def drawStar(
g: Graphics2D,
cx: Int,
cy: Int,
outer: Int,
inner: Int
): Unit = {
val poly =
new java.awt.Polygon()
var i: Int =
0
while (
i < 10
) {
val angle =
-math.Pi / 2.0 +
i * math.Pi / 5.0
val radius =
if (i % 2 == 0)
outer
else
inner
poly.addPoint(
cx +
(math.cos(angle) * radius).toInt,
cy +
(math.sin(angle) * radius).toInt
)
i += 1
}
g.fillPolygon(
poly
)
}
// ============================================================
// PEACOCK FEATHER
// ============================================================
def drawPeacockFeather(
g: Graphics2D,
x: Int,
y: Int,
scale: Double
): Unit = {
g.setStroke(
new BasicStroke(
math.max(
2.0f,
(5.0 * scale).toFloat
)
)
)
g.setColor(
new Color(
30,
120,
70
)
)
g.drawLine(
x,
y + (85 * scale).toInt,
x + (18 * scale).toInt,
y
)
g.setColor(
new Color(
30,
150,
180
)
)
g.fillOval(
x - (16 * scale).toInt,
y - (18 * scale).toInt,
(32 * scale).toInt,
(45 * scale).toInt
)
g.setColor(
new Color(
50,
70,
190
)
)
g.fillOval(
x - (10 * scale).toInt,
y - (10 * scale).toInt,
(20 * scale).toInt,
(28 * scale).toInt
)
g.setColor(
new Color(
30,
170,
100
)
)
g.fillOval(
x - (6 * scale).toInt,
y - (5 * scale).toInt,
(12 * scale).toInt,
(18 * scale).toInt
)
g.setColor(
new Color(
20,
40,
80
)
)
g.fillOval(
x - (3 * scale).toInt,
y - (1 * scale).toInt,
(6 * scale).toInt,
(10 * scale).toInt
)
}
// ============================================================
// KRISHNA-LIKE FESTIVE FIGURE
// ============================================================
def drawDivineFigure(
g: Graphics2D
): Unit = {
val cx: Int =
610
val cy: Int =
525
// BODY GLOW
drawGlow(
g,
cx,
cy - 40,
120,
35
)
// BODY
g.setColor(
new Color(
65,
105,
185
)
)
g.fillRoundRect(
cx - 52,
cy - 40,
104,
135,
42,
42
)
// FACE
g.setColor(
new Color(
90,
125,
205
)
)
g.fillOval(
cx - 46,
cy - 125,
92,
102
)
// HAIR
g.setColor(
new Color(
25,
20,
45
)
)
g.fillOval(
cx - 50,
cy - 148,
100,
65
)
g.fillOval(
cx - 58,
cy - 115,
40,
60
)
g.fillOval(
cx + 18,
cy - 118,
40,
63
)
// EYES
g.setColor(
Color.BLACK
)
g.fillOval(
cx - 28,
cy - 90,
11,
8
)
g.fillOval(
cx + 17,
cy - 90,
11,
8
)
// TILAK
g.setColor(
new Color(
255,
245,
220
)
)
g.fillRoundRect(
cx - 3,
cy - 88,
6,
26,
3,
3
)
// CROWN
g.setColor(
new Color(
220,
160,
30
)
)
val crown =
new java.awt.Polygon()
crown.addPoint(
cx - 62,
cy - 135
)
crown.addPoint(
cx - 35,
cy - 178
)
crown.addPoint(
cx - 12,
cy - 150
)
crown.addPoint(
cx + 8,
cy - 184
)
crown.addPoint(
cx + 29,
cy - 150
)
crown.addPoint(
cx + 55,
cy - 172
)
crown.addPoint(
cx + 65,
cy - 132
)
crown.addPoint(
cx - 62,
cy - 135
)
g.fillPolygon(
crown
)
// CROWN JEWELS
g.setColor(
new Color(
80,
220,
240
)
)
g.fillOval(
cx - 8,
cy - 164,
16,
16
)
g.setColor(
new Color(
255,
100,
140
)
)
g.fillOval(
cx - 42,
cy - 151,
11,
11
)
g.fillOval(
cx + 31,
cy - 150,
11,
11
)
// PEACOCK FEATHER
drawPeacockFeather(
g,
cx + 25,
cy - 185,
1.15
)
// NECKLACE
g.setColor(
new Color(
240,
190,
50
)
)
g.setStroke(
new BasicStroke(
4
)
)
g.drawArc(
cx - 42,
cy - 10,
84,
42,
200,
140
)
// FLUTE
val fluteY: Int =
cy + 8 +
(
math.sin(flutePulse) *
4
).toInt
g.setColor(
new Color(
215,
165,
65
)
)
g.setStroke(
new BasicStroke(
8,
BasicStroke.CAP_ROUND,
BasicStroke.JOIN_ROUND
)
)
g.drawLine(
cx - 80,
fluteY,
cx + 80,
fluteY
)
g.setColor(
new Color(
60,
35,
20
)
)
var holeIndex: Int =
-2
while (
holeIndex <= 2
) {
g.fillOval(
cx + holeIndex * 25 - 3,
fluteY - 3,
6,
6
)
holeIndex += 1
}
// ARMS
g.setColor(
new Color(
75,
115,
195
)
)
g.setStroke(
new BasicStroke(
13,
BasicStroke.CAP_ROUND,
BasicStroke.JOIN_ROUND
)
)
g.drawLine(
cx - 35,
cy - 5,
cx - 88,
cy + 18
)
g.drawLine(
cx + 35,
cy - 5,
cx + 88,
cy - 4
)
// CLOTH
g.setColor(
new Color(
245,
175,
35
)
)
g.fillArc(
cx - 70,
cy + 65,
140,
80,
180,
180
)
// FEET
g.setColor(
new Color(
75,
115,
195
)
)
g.fillOval(
cx - 52,
cy + 104,
35,
22
)
g.fillOval(
cx + 18,
cy + 104,
35,
22
)
}
// ============================================================
// BUTTER POT
// ============================================================
def drawButterPot(
g: Graphics2D
): Unit = {
val cx: Int =
610
val topY: Int =
155
g.setColor(
new Color(
120,
75,
35
)
)
g.fillRoundRect(
cx - 48,
topY + 35,
96,
100,
28,
28
)
g.setColor(
Color.WHITE
)
g.fillOval(
cx - 43,
topY + 20,
86,
40
)
g.setColor(
new Color(
255,
235,
170
)
)
g.fillOval(
cx - 27,
topY + 32,
54,
27
)
g.setColor(
new Color(
210,
150,
55
)
)
g.setStroke(
new BasicStroke(
6
)
)
g.drawArc(
cx - 60,
topY + 10,
120,
120,
175,
185
)
// HANGING ROPE
g.drawLine(
cx - 42,
topY - 55,
cx - 42,
topY + 20
)
g.drawLine(
cx + 42,
topY - 55,
cx + 42,
topY + 20
)
g.drawLine(
cx - 42,
topY - 55,
cx + 42,
topY - 55
)
}
// ============================================================
// JANMASHTAMI CRADLE
// ============================================================
def drawCradle(
g: Graphics2D
): Unit = {
val cx: Int =
610
val y: Int =
610 +
(
math.sin(swingAngle) *
9
).toInt
// SUPPORT POSTS
g.setStroke(
new BasicStroke(
12,
BasicStroke.CAP_ROUND,
BasicStroke.JOIN_ROUND
)
)
g.setColor(
new Color(
115,
65,
30
)
)
g.drawLine(
cx - 105,
450,
cx - 72,
y - 30
)
g.drawLine(
cx + 105,
450,
cx + 72,
y - 30
)
// CHAINS
g.setColor(
new Color(
230,
175,
60
)
)
g.setStroke(
new BasicStroke(
5
)
)
g.drawLine(
cx - 72,
y - 30,
cx - 54,
y + 8
)
g.drawLine(
cx + 72,
y - 30,
cx + 54,
y + 8
)
// CRADLE
g.setColor(
new Color(
165,
85,
35
)
)
g.fillRoundRect(
cx - 92,
y,
184,
48,
22,
22
)
g.setColor(
new Color(
245,
185,
50
)
)
g.setStroke(
new BasicStroke(
5
)
)
g.drawRoundRect(
cx - 92,
y,
184,
48,
22,
22
)
// PILLOW
g.setColor(
new Color(
250,
245,
220
)
)
g.fillRoundRect(
cx - 75,
y - 17,
150,
28,
20,
20
)
// TINY DIVINE ICON
g.setColor(
new Color(
70,
110,
190
)
)
g.fillOval(
cx - 18,
y - 10,
36,
30
)
drawPeacockFeather(
g,
cx + 10,
y - 32,
0.45
)
}
// ============================================================
// CLOUD
// ============================================================
def drawCloud(
g: Graphics2D,
x: Int,
y: Int,
scale: Int
): Unit = {
g.setColor(
new Color(
255,
255,
255,
185
)
)
g.fillOval(
x,
y,
scale * 2,
scale
)
g.fillOval(
x + scale,
y - scale / 2,
scale * 2,
scale + scale / 2
)
g.fillOval(
x + scale * 2,
y,
scale * 2,
scale
)
}
// ============================================================
// HILLS
// ============================================================
def drawHills(
g: Graphics2D
): Unit = {
g.setColor(
new Color(
30,
95,
65
)
)
val p =
new java.awt.Polygon()
p.addPoint(
0,
590
)
p.addPoint(
170,
500
)
p.addPoint(
310,
570
)
p.addPoint(
455,
480
)
p.addPoint(
620,
565
)
p.addPoint(
790,
490
)
p.addPoint(
960,
565
)
p.addPoint(
SCREEN_W,
510
)
p.addPoint(
SCREEN_W,
SCREEN_H
)
p.addPoint(
0,
SCREEN_H
)
g.fillPolygon(
p
)
}
// ============================================================
// LOTUS
// ============================================================
def drawLotus(
g: Graphics2D,
x: Int,
y: Int
): Unit = {
g.setColor(
new Color(
255,
135,
185
)
)
g.fillOval(
x - 35,
y - 8,
40,
25
)
g.fillOval(
x - 5,
y - 8,
40,
25
)
g.fillOval(
x - 22,
y - 22,
44,
30
)
g.setColor(
new Color(
245,
190,
230
)
)
g.fillOval(
x - 12,
y - 18,
24,
20
)
}
// ============================================================
// MAHADWAR / ARCH
// ============================================================
def drawTempleArch(
g: Graphics2D
): Unit = {
g.setColor(
new Color(
180,
115,
45
)
)
g.fillRoundRect(
40,
180,
175,
350,
35,
35
)
g.setColor(
new Color(
55,
35,
30
)
)
g.fillRoundRect(
70,
250,
115,
280,
40,
40
)
g.setColor(
new Color(
245,
185,
55
)
)
g.setStroke(
new BasicStroke(
7
)
)
g.drawRoundRect(
47,
187,
161,
337,
35,
35
)
g.setColor(
new Color(
250,
220,
100
)
)
drawStar(
g,
128,
220,
20,
9
)
}
// ============================================================
// WATER
// ============================================================
def drawWater(
g: Graphics2D
): Unit = {
g.setColor(
new Color(
40,
125,
190
)
)
g.fillRect(
0,
650,
SCREEN_W,
110
)
g.setColor(
new Color(
255,
255,
255,
110
)
)
g.setStroke(
new BasicStroke(
2
)
)
var wx: Int =
0
while (
wx < SCREEN_W
) {
val waveY =
680 +
(
math.sin(
elapsed * 2.0 +
wx * 0.035
) *
4
).toInt
g.drawLine(
wx,
waveY,
wx + 55,
waveY
)
wx += 70
}
}
// ============================================================
// MAIN PANEL
// ============================================================
val festivalPanel =
new JPanel {
setPreferredSize(
new Dimension(
SCREEN_W,
SCREEN_H
)
)
override def paintComponent(
graphics: Graphics
): Unit = {
super.paintComponent(
graphics
)
val g =
graphics.asInstanceOf[
Graphics2D
]
g.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON
)
g.setRenderingHint(
RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_QUALITY
)
// ======================================================
// SKY
// ======================================================
g.setPaint(
new GradientPaint(
0,
0,
new Color(
14,
18,
70
),
0,
SCREEN_H,
new Color(
255,
170,
95
)
)
)
g.fillRect(
0,
0,
SCREEN_W,
SCREEN_H
)
// ======================================================
// MOON GLOW
// ======================================================
val moonX: Int =
1000
val moonY: Int =
135
val moonRadius: Int =
54 +
(
math.sin(moonPulse) *
5
).toInt
drawGlow(
g,
moonX,
moonY,
120,
30
)
g.setColor(
new Color(
255,
248,
210
)
)
g.fillOval(
moonX - moonRadius,
moonY - moonRadius,
moonRadius * 2,
moonRadius * 2
)
// ======================================================
// STARS
// ======================================================
var si: Int =
0
while (
si < stars.length
) {
val st =
stars(si)
val twinkle =
(
math.sin(
elapsed * 2.0 +
st.phase
) *
0.5 +
0.5
)
val size =
math.max(
1,
(
st.size +
twinkle * 2.0
).toInt
)
g.setColor(
new Color(
255,
245,
190,
160 + (twinkle * 90).toInt
)
)
g.fillOval(
st.x.toInt,
st.y.toInt,
size,
size
)
st.y =
st.y +
st.speed * 0.18
if (
st.y > 480
) {
st.y =
50
}
si += 1
}
// ======================================================
// CLOUDS
// ======================================================
drawCloud(
g,
250,
100,
45
)
drawCloud(
g,
760,
190,
35
)
drawCloud(
g,
380,
230,
28
)
// ======================================================
// TITLE GLOW
// ======================================================
val titleAlpha =
150 +
(
(
math.sin(titlePulse) *
0.5 +
0.5
) * 90
).toInt
g.setColor(
new Color(
255,
215,
90,
titleAlpha
)
)
g.setFont(
new Font(
"Serif",
Font.BOLD,
43
)
)
val title =
"? ??? ???? ????? ?????? ?"
val titleWidth =
g.getFontMetrics.stringWidth(
title
)
g.drawString(
title,
(SCREEN_W - titleWidth) / 2,
62
)
g.setFont(
new Font(
"Arial",
Font.BOLD,
17
)
)
g.setColor(
new Color(
255,
250,
230,
220
)
)
val subtitle =
"A luminous festival night in Gokul"
val subtitleWidth =
g.getFontMetrics.stringWidth(
subtitle
)
g.drawString(
subtitle,
(SCREEN_W - subtitleWidth) / 2,
90
)
// ======================================================
// TEMPLE
// ======================================================
drawTempleArch(
g
)
// ======================================================
// HILLS
// ======================================================
drawHills(
g
)
// ======================================================
// TREES
// ======================================================
var treeX: Int =
250
while (
treeX < 1120
) {
g.setColor(
new Color(
55,
105,
45
)
)
g.fillRect(
treeX,
455,
18,
130
)
g.setColor(
new Color(
30,
125,
55
)
)
g.fillOval(
treeX - 45,
405,
105,
100
)
g.fillOval(
treeX + 5,
385,
100,
105
)
treeX += 190
}
// ======================================================
// LOTUS
// ======================================================
drawLotus(
g,
305,
650
)
drawLotus(
g,
930,
650
)
// ======================================================
// WATER
// ======================================================
drawWater(
g
)
// ======================================================
// BUTTER POT
// ======================================================
drawButterPot(
g
)
// ======================================================
// DIVINE FIGURE
// ======================================================
drawDivineFigure(
g
)
// ======================================================
// CRADLE
// ======================================================
drawCradle(
g
)
// ======================================================
// FLOWER PARTICLES
// ======================================================
var fi: Int =
flowers.length - 1
while (
fi >= 0
) {
val f =
flowers(fi)
val flowerSize =
7 + f.kind * 2
val petalColor =
if (f.kind == 0)
new Color(
255,
110,
165
)
else if (f.kind == 1)
new Color(
255,
215,
80
)
else if (f.kind == 2)
new Color(
175,
115,
255
)
else
new Color(
255,
150,
90
)
g.setColor(
petalColor
)
g.fillOval(
f.x.toInt - flowerSize,
f.y.toInt - flowerSize / 2,
flowerSize,
flowerSize
)
g.fillOval(
f.x.toInt,
f.y.toInt - flowerSize,
flowerSize,
flowerSize
)
g.fillOval(
f.x.toInt,
f.y.toInt,
flowerSize,
flowerSize
)
g.fillOval(
f.x.toInt - flowerSize,
f.y.toInt,
flowerSize,
flowerSize
)
g.setColor(
Color.YELLOW
)
g.fillOval(
f.x.toInt,
f.y.toInt,
4,
4
)
f.x =
f.x + f.vx
f.y =
f.y + f.vy
f.vy =
f.vy + 0.045
f.life =
f.life - 1
if (
f.life <= 0 ||
f.y > SCREEN_H
) {
flowers.remove(
fi
)
}
fi -= 1
}
// ======================================================
// SPARKS
// ======================================================
var spi: Int =
sparks.length - 1
while (
spi >= 0
) {
val s =
sparks(spi)
val a =
math.max(
0,
math.min(
255,
s.life * 6
)
)
g.setColor(
new Color(
255,
225,
100,
a
)
)
g.fillOval(
s.x.toInt - s.size / 2,
s.y.toInt - s.size / 2,
s.size,
s.size
)
s.x =
s.x + s.vx
s.y =
s.y + s.vy
s.vy =
s.vy + 0.035
s.life =
s.life - 1
if (
s.life <= 0
) {
sparks.remove(
spi
)
}
spi -= 1
}
// ======================================================
// BUTTER PARTICLES
// ======================================================
var bi: Int =
butterParticles.length - 1
while (
bi >= 0
) {
val b =
butterParticles(bi)
g.setColor(
new Color(
255,
238,
155,
math.max(
0,
math.min(
255,
b.life * 4
)
)
)
)
g.fillOval(
b.x.toInt,
b.y.toInt,
b.size,
b.size
)
b.x =
b.x + b.vx
b.y =
b.y + b.vy
b.vy =
b.vy + 0.05
b.life =
b.life - 1
if (
b.life <= 0
) {
butterParticles.remove(
bi
)
}
bi -= 1
}
// ======================================================
// FESTIVAL SIDE GLOW
// ======================================================
drawGlow(
g,
115,
600,
70,
20
)
drawGlow(
g,
1085,
600,
70,
20
)
// ======================================================
// BOTTOM INFO
// ======================================================
g.setColor(
new Color(
20,
15,
40,
175
)
)
g.fillRoundRect(
300,
700,
600,
42,
20,
20
)
g.setColor(
new Color(
255,
240,
180
)
)
g.setFont(
new Font(
"Arial",
Font.BOLD,
18
)
)
val info =
"? ????? ?????? ? ???? ? ???? ? ????? ? ???? ? ???? ?"
val infoWidth =
g.getFontMetrics.stringWidth(
info
)
g.drawString(
info,
(SCREEN_W - infoWidth) / 2,
728
)
}
}
// ============================================================
// MOUSE INTERACTION
// ============================================================
festivalPanel.addMouseListener(
new MouseAdapter {
override def mousePressed(
e: MouseEvent
): Unit = {
var i: Int =
0
while (
i < 7
) {
addSpark(
e.getX,
e.getY
)
i += 1
}
addButterParticle(
e.getX,
e.getY
)
butterCount =
butterCount + 1
festivalPanel.repaint()
}
}
)
// ============================================================
// MOUSE MOTION
// ============================================================
festivalPanel.addMouseMotionListener(
new MouseMotionAdapter {
override def mouseMoved(
e: MouseEvent
): Unit = {
if (
rnd.nextInt(8) == 0
) {
addSpark(
e.getX,
e.getY
)
}
festivalPanel.repaint()
}
}
)
// ============================================================
// START BUTTON
// ============================================================
val startButton =
new JButton(
"FESTIVAL"
)
startButton.setFocusable(
false
)
// ============================================================
// TOGGLE BUTTON
// ============================================================
startButton.addActionListener(
new ActionListener {
override def actionPerformed(
e: ActionEvent
): Unit = {
running =
!running
if (running) {
startButton.setText(
"PAUSE"
)
} else {
startButton.setText(
"PLAY"
)
}
}
}
)
// ============================================================
// FRAME
// ============================================================
val frame =
new JFrame(
"ULTRA GOKUL ASHTAMI FESTIVAL"
)
frame.setDefaultCloseOperation(
WindowConstants.EXIT_ON_CLOSE
)
frame.setLayout(
new BorderLayout()
)
frame.add(
festivalPanel,
BorderLayout.CENTER
)
frame.add(
startButton,
BorderLayout.SOUTH
)
frame.setResizable(
false
)
frame.pack()
frame.setLocationRelativeTo(
null
)
// ============================================================
// ANIMATION TIMER
// ============================================================
val animationTimer: Timer =
new Timer(
30,
new ActionListener {
override def actionPerformed(
e: ActionEvent
): Unit = {
if (running) {
elapsed =
elapsed + 0.03
moonPulse =
moonPulse + 0.025
glowPulse =
glowPulse + 0.04
flutePulse =
flutePulse + 0.06
titlePulse =
titlePulse + 0.055
// SWING MOTION
swingAngle =
swingAngle +
0.035 *
swingDirection
if (
math.abs(swingAngle) >
0.36
) {
swingDirection =
-swingDirection
}
// RANDOM FLOWERS
if (
flowers.length < 22 &&
rnd.nextInt(4) == 0
) {
addFlower(
420 +
rnd.nextDouble() * 400,
610
)
}
// RANDOM SPARKS
if (
rnd.nextInt(5) == 0
) {
addSpark(
600 +
math.sin(elapsed) * 70,
500 +
math.cos(elapsed * 1.3) * 30
)
}
// RANDOM BUTTER
if (
rnd.nextInt(18) == 0
) {
addButterParticle(
610 +
rnd.nextDouble() * 55 -
27,
180
)
}
festivalPanel.repaint()
}
}
}
)
// ============================================================
// WINDOW CLOSE -> STOP TIMER
// ============================================================
frame.addWindowListener(
new java.awt.event.WindowAdapter {
override def windowClosed(
e: java.awt.event.WindowEvent
): Unit = {
animationTimer.stop()
running = false
}
}
)
// ============================================================
// SHOW
// ============================================================
SwingUtilities.invokeLater(
new Runnable {
override def run(): Unit = {
startButton.setText(
"PAUSE"
)
frame.setVisible(
true
)
festivalPanel.requestFocusInWindow()
}
}
)
// ============================================================
// START ANIMATION
// ============================================================
animationTimer.start()