Code Sketch
swarali sandip sutar
Category: Art
import javax.swing._
import java.awt._
import java.awt.event._
import java.awt.geom._
import scala.collection.mutable.ArrayBuffer
object SolarSystem3DApp {
def main(args: Array[String]): Unit = {
SwingUtilities.invokeLater(new Runnable {
def run(): Unit = {
val frame = new JFrame("3D Solar System Animation - Scala / Kojo")
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE)
frame.setSize(1024, 768)
frame.setLocationRelativeTo(null)
val panel = new SolarSystemPanel()
frame.setContentPane(panel)
frame.setVisible(true)
}
})
}
}
class Planet(val name: String, val distance: Double, val radius: Int, val speed: Double, val color: Color) {
var angle: Double = java.lang.Math.random() * 2 * java.lang.Math.PI
}
class SolarSystemPanel extends JPanel {
setBackground(new Color(10, 10, 20))
// Initialize planets with orbital distance, radius, orbital speed, and color
val planets = ArrayBuffer(
new Planet("Mercury", 75, 5, 0.04, new Color(169, 169, 169)),
new Planet("Venus", 120, 8, 0.015, new Color(218, 165, 32)),
new Planet("Earth", 175, 10, 0.01, new Color(70, 130, 180)),
new Planet("Mars", 235, 7, 0.008, new Color(205, 92, 92)),
new Planet("Jupiter", 320, 18, 0.004, new Color(222, 184, 135)),
new Planet("Saturn", 400, 15, 0.003, new Color(238, 232, 170)),
new Planet("Uranus", 480, 12, 0.002, new Color(135, 206, 250)),
new Planet("Neptune", 550, 12, 0.0015, new Color(65, 105, 225))
)
// Starfield background generation
case class Star(x: Int, y: Int, size: Int, var brightness: Float)
val stars = ArrayBuffer[Star]()
for (_ <- 1 to 250) {
stars += Star(
(java.lang.Math.random() * 1200).toInt,
(java.lang.Math.random() * 900).toInt,
(java.lang.Math.random() * 3).toInt + 1,
(java.lang.Math.random() * 0.7 + 0.3).toFloat
)
}
// Animation Timer (approx. 30 FPS)
val timer = new Timer(30, new ActionListener {
override def actionPerformed(e: ActionEvent): Unit = {
for (p <- planets) {
p.angle += p.speed
}
// Twinkle stars slightly
for (s <- stars) {
s.brightness = java.lang.Math.max(0.2f, java.lang.Math.min(1.0f, s.brightness + (java.lang.Math.random() * 0.2 - 0.1).toFloat))
}
repaint()
}
})
timer.start()
override def paintComponent(g: Graphics): Unit = {
super.paintComponent(g)
val g2 = g.asInstanceOf[Graphics2D]
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON)
val w = getWidth
val h = getHeight
val cx = w / 2
val cy = h / 2
// 1. Draw Starfield
for (s <- stars) {
g2.setColor(Color.WHITE)
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, s.brightness))
g2.fillOval(s.x, s.y, s.size, s.size)
}
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1.0f))
// Pseudo-3D orbital tilt factor (isometric / perspective inclination)
val tilt = 0.45
// 2. Draw Dashed Orbit Paths
g2.setColor(new Color(255, 255, 255, 35))
g2.setStroke(new BasicStroke(1.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, 1.0f, Array(5f, 5f), 0f))
for (p <- planets) {
val orbitW = (p.distance * 2).toInt
val orbitH = (p.distance * 2 * tilt).toInt
g2.drawOval(cx - p.distance.toInt, cy - (p.distance * tilt).toInt, orbitW, orbitH)
}
g2.setStroke(new BasicStroke(1.0f))
// 3. Draw Sun with Glowing Radial Gradient
val sunRadius = 38
val sunGradient = new RadialGradientPaint(
cx, cy, sunRadius * 1.8f,
Array(0.0f, 0.5f, 1.0f),
Array(Color.YELLOW, new Color(255, 140, 0, 220), new Color(255, 69, 0, 0))
)
g2.setPaint(sunGradient)
g2.fillOval(cx - sunRadius * 2, cy - sunRadius * 2, sunRadius * 4, sunRadius * 4)
g2.setColor(new Color(255, 220, 50))
g2.fillOval(cx - sunRadius, cy - sunRadius, sunRadius * 2, sunRadius * 2)
// 4. Calculate Planet Positions & Depth Sort for 3D Overlap
case class RenderablePlanet(planet: Planet, x: Double, y: Double, depth: Double)
val renderList = ArrayBuffer[RenderablePlanet]()
for (p <- planets) {
val px = cx + p.distance * java.lang.Math.cos(p.angle)
val py = cy + (p.distance * java.lang.Math.sin(p.angle)) * tilt
renderList += RenderablePlanet(p, px, py, py) // py acts as depth for sorting
}
// Sort by depth so background planets render behind foreground planets
val sortedPlanets = renderList.sortBy(_.depth)
// 5. Render Planets and Labels
for (rp <- sortedPlanets) {
val p = rp.planet
val x = rp.x.toInt
val y = rp.y.toInt
// 3D Spherical Shading Gradient
val planetGradient = new RadialGradientPaint(
x - p.radius / 3, y - p.radius / 3, p.radius * 1.3f,
Array(0.0f, 0.85f, 1.0f),
Array(Color.WHITE, p.color, new Color(15, 15, 25))
)
g2.setPaint(planetGradient)
g2.fillOval(x - p.radius, y - p.radius, p.radius * 2, p.radius * 2)
// Saturn Rings Special Rendering
if (p.name == "Saturn") {
g2.setColor(new Color(210, 180, 140, 160))
g2.setStroke(new BasicStroke(3.5f))
g2.drawOval(x - p.radius * 2, y - p.radius / 2, p.radius * 4, p.radius)
}
// Planet Name Tag
g2.setColor(new Color(200, 210, 230))
g2.setFont(new Font("SansSerif", Font.BOLD, 11))
g2.drawString(p.name, x + p.radius + 5, y + 4)
}
// Header Title
g2.setColor(Color.WHITE)
g2.setFont(new Font("SansSerif", Font.BOLD, 16))
g2.drawString("SOLAR SYSTEM 3D ORBITAL SIMULATION", 25, 35)
}
}
// Automatically start the application in Kojo or standard Scala
SolarSystem3DApp.main(Array())