python-grav-sim/main.py
2024-08-15 17:25:40 +02:00

140 lines
No EOL
3.3 KiB
Python

from tkinter import *
from math import sqrt
from time import sleep
WIDTH = 1400
HEIGHT = 800
class Planet:
def __init__(self, canvas, size, mass, color, x, y):
self.canvas = canvas
self.size = size
self.mass = mass
self.color = color
self.x = x
self.y = y
self.dx = 0
self.dy = 0
self.ax = 0
self.ay = 0
def draw(self, scale, dt):
self.x += self.dx * dt
self.y += self.dy * dt
x1 = (self.x - self.size) / scale + WIDTH / 2
y1 = (self.y - self.size) / scale + HEIGHT / 2
x2 = (self.x + self.size) / scale + WIDTH / 2
y2 = (self.y + self.size) / scale + HEIGHT / 2
self.canvas.create_oval(x1, y1, x2, y2, fill=self.color)
def calculate_acceleration(self, planet):
G = 6.67 * pow(10, -11)
dx = planet.x - self.x
dy = planet.y - self.y
d = sqrt(dx ** 2 + dy ** 2)
if d == 0:
return (0, 0)
F = G * self.mass * planet.mass / d ** 2
self.ax += F * dx / (d * self.mass)
self.ay += F * dy / (d * self.mass)
def update_velocity(self, dt):
self.dx += self.ax * dt
self.dy += self.ay * dt
self.ax = 0
self.ay = 0
def set_initial_velocity(self, dx, dy):
self.dx = dx
self.dy = dy
def orbit(self, planet):
G = 6.67e-11
M = planet.mass
r = sqrt((self.x - planet.x)**2 + (self.y - planet.y)**2)
v = sqrt(G * M / r)
vec_x = (self.x - planet.x) / r
vec_y = (self.y - planet.y) / r
n_x = vec_y * -1
n_y = vec_x * 1
n_len = sqrt(n_x ** 2 + n_y ** 2)
n_x /= n_len
n_y /= n_len
self.set_initial_velocity(n_x * v, n_y * v)
class System():
def __init__(self, canvas):
self.planets = []
self.canvas = canvas
def add(self, planet):
self.planets.append(planet)
def update_all(self, dt, scale):
for planet1 in self.planets:
for planet2 in self.planets:
if planet1 != planet2:
planet1.calculate_acceleration(planet2)
planet1.update_velocity(dt)
self.canvas.delete("all")
for planet in self.planets:
planet.draw(scale, dt)
def main():
window = Tk()
window.title("Simple Grav Sim")
canvas = Canvas(window, bg="black", width=WIDTH, height=HEIGHT)
canvas.pack()
time = Scale(window, from_=1, to=1_000_000, orient=HORIZONTAL, length=400)
time.pack()
scale = Scale(window, to=1, from_=5_000_000, orient=HORIZONTAL, length=400)
scale.pack()
scale.set(460_000)
fps = Scale(window, from_=1, to=1000, orient=HORIZONTAL)
fps.pack()
fps.set(75)
system = System(canvas)
earth = Planet(canvas, 6_371_000, 5.972e24, "green", 0, 0)
moon = Planet(canvas, 1_737_400, 7.348e22, "grey", 384_400_000, 80_000_000)
blue_moon = Planet(canvas, 837_400, 10_000, "blue", 400_000, 80_000_000)
system.add(earth)
system.add(moon)
system.add(blue_moon)
moon.orbit(earth)
blue_moon.orbit(earth)
while True:
system.update_all(time.get() / fps.get(), scale.get())
window.update_idletasks()
window.update()
sleep(1 / fps.get())
if __name__ == "__main__":
main()