140 lines
No EOL
3.3 KiB
Python
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() |