The simulation is built using Python libraries like NumPy for calculations and Matplotlib for visualization and animation. A central Sun is created using circular patches, and multiple planets are initialized with different distances, sizes, and velocities.
Each planet is represented by its position, velocity, and a trail to show its path. The motion is updated frame by frame inside an animation function. At every step, the distance of the planet from the center is calculated, and gravitational acceleration is applied to update its velocity and position.
The animation uses a loop-based update method, where new positions are continuously computed and plotted. Trails are generated using line segments with fading colors to create a smooth orbital path effect.
The structure is scalable, allowing multiple planets to be handled using a list and iterating over them. This keeps the code clean and efficient while simulating complex motion.
Overall, the code combines physics calculations with visualization techniques to create a dynamic and visually appealing model of planetary motion.
Video Explanation
Python Program
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
from matplotlib.collections import LineCollection
from matplotlib.patches import Circle
# --- Figure setup ---
fig, ax = plt.subplots()
ax.set_xlim(-3.5, 3.5)
ax.set_ylim(-3.5, 3.5)
ax.set_aspect("equal")
ax.axis("off")
fig.patch.set_facecolor('black')
# --- Sun (core + glow) ---
sun_glow = Circle((0, 0), 0.4, color='yellow', alpha=0.2)
sun = Circle((0, 0), 0.18, color='orange')
ax.add_patch(sun_glow)
ax.add_patch(sun)
# --- Gravity constants ---
G = 1
M = 1
# --- Planet data (distance, size, color) ---
planets_data = [
("Mercury", 0.5, 0.02, 'gray'),
("Venus", 0.7, 0.03, 'orange'),
("Earth", 1.0, 0.04, 'blue'),
("Mars", 1.3, 0.035, 'red'),
("Jupiter", 1.8, 0.07, 'brown'),
("Saturn", 2.3, 0.06, 'gold'),
("Uranus", 2.8, 0.05, 'cyan'),
("Neptune", 3.2, 0.05, 'purple'),
]
# --- Create planets ---
planets = []
for name, r, size, color in planets_data:
# --- orbital velocity ---
v = np.sqrt(G * M / r)
v *= 0.98 # slight ellipse (optional)
glow = Circle((r, 0), size*2, color=color, alpha=0.2)
body = Circle((r, 0), size, color=color)
ax.add_patch(glow)
ax.add_patch(body)
planet = {
"x": r, "y": 0,
"vx": 0, "vy": v,
"points": [],
"trail": LineCollection([], linewidths=2),
"glow": glow,
"body": body,
"color": color
}
ax.add_collection(planet["trail"])
planets.append(planet)
# --- Time step ---
dt = 0.02
MAX_POINTS = 300
def update(frame):
global planets
for p in planets:
x, y = p["x"], p["y"]
vx, vy = p["vx"], p["vy"]
# --- Gravity ---
r = np.sqrt(x**2 + y**2)
ax_g = -G * M * x / r**3
ay_g = -G * M * y / r**3
vx += ax_g * dt
vy += ay_g * dt
x += vx * dt
y += vy * dt
p["x"], p["y"] = x, y
p["vx"], p["vy"] = vx, vy
# --- Save path ---
p["points"].append([x, y])
if len(p["points"]) > MAX_POINTS:
p["points"] = p["points"][-MAX_POINTS:]
# --- Build fading trail ---
segments = []
colors = []
widths = []
for i in range(len(p["points"]) - 1):
segments.append([p["points"][i], p["points"][i + 1]])
alpha = i / len(p["points"])
# --- simple color fade ---
colors.append((1, 1, 1, alpha))
widths.append(0.5 + 2 * alpha)
p["trail"].set_segments(segments)
p["trail"].set_color(colors)
p["trail"].set_linewidth(widths)
# --- Move planet ---
p["body"].center = (x, y)
p["glow"].center = (x, y)
return [p["trail"] for p in planets] + [p["body"] for p in planets]
ani = FuncAnimation(fig, update, frames=3000, interval=20)
plt.show()
Output
