252 lines
5.5 KiB
Python
Executable file
252 lines
5.5 KiB
Python
Executable file
#!/usr/bin/python
|
|
import pygame
|
|
from pygame.locals import *
|
|
import os
|
|
import sys
|
|
import math
|
|
import random
|
|
|
|
"""
|
|
Units of measure:
|
|
1 pixel represents 10^9 m
|
|
1 unit of speed represents 10^9 m/day
|
|
1 unit of mass represents 10^24 kg
|
|
graviational constant
|
|
"""
|
|
grav_const = 6.6742
|
|
|
|
pause = True
|
|
lock_index = 0
|
|
def handle_key_ev(key):
|
|
global bounce, speed_player, trails, dir_player, color_player, lock, lock_index, pause
|
|
if key == K_b:
|
|
bounce = not bounce
|
|
elif key == K_q:
|
|
sys.exit(0)
|
|
elif key == K_c:
|
|
scr.fill((0,0,0))
|
|
elif key == K_t:
|
|
trails = not trails
|
|
elif key == K_s:
|
|
lock = sun
|
|
elif key == K_e:
|
|
lock = earth
|
|
elif key == K_u:
|
|
lock = None
|
|
elif key == K_n:
|
|
lock_index += 1
|
|
if lock_index >= len(slaves):
|
|
lock_index = 0
|
|
lock = slaves[lock_index]
|
|
elif key == K_EQUALS:
|
|
rescale(scale * 1.5)
|
|
elif key == K_MINUS:
|
|
rescale(scale / 1.5)
|
|
elif key == K_p:
|
|
pause = not pause
|
|
|
|
def rescale(newscale):
|
|
global scale
|
|
scale = newscale
|
|
scr.fill((0,0,0))
|
|
|
|
|
|
def handle_keys(keys):
|
|
global bounce, speed_player, trails, dir_player, color_player
|
|
for key in keys:
|
|
if key == K_UP:
|
|
speed_player += 0.01
|
|
elif key == K_DOWN:
|
|
speed_player -= 0.01
|
|
elif key == K_LEFT:
|
|
dir_player -= (math.pi / 180.0)
|
|
elif key == K_RIGHT:
|
|
dir_player += (math.pi / 180.0)
|
|
|
|
|
|
def xy2dir(coords):
|
|
if abs(coords[0]) < 0.00000001 and abs(coords[1]) > 0.000001:
|
|
res = math.pi
|
|
elif coords[0] == 0:
|
|
res = math.pi
|
|
else:
|
|
res = math.atan(coords[1] / coords[0]) + (math.pi/2)
|
|
|
|
if coords[0] < 0:
|
|
res += math.pi
|
|
return res
|
|
|
|
class Vector(object):
|
|
def __init__(self, dir, mag):
|
|
self.dir = float(dir)
|
|
self.mag = float(mag)
|
|
def __add__(self, other):
|
|
va = self.resolve()
|
|
vb = other.resolve()
|
|
vf = [va[0] + vb[0], va[1] + vb[1]]
|
|
|
|
newmag = math.sqrt(vf[0]**2 + vf[1]**2)
|
|
newdir = xy2dir(vf)
|
|
return Vector(newdir, newmag)
|
|
|
|
def __sub__(self, other):
|
|
return self + Vector(other.dir, -other.mag)
|
|
|
|
def __mul__(self, scalar):
|
|
self.mag *= scalar
|
|
def __div__(self, scalar):
|
|
self.mag /= scalar
|
|
|
|
def resolve(self):
|
|
return [(math.sin(self.dir) * self.mag), -(math.cos(self.dir) * self.mag)]
|
|
def __repr__(self):
|
|
return "<Vector(dir=%f, mag=%f)>" % (self.dir, self.mag)
|
|
|
|
class GravitySlave(object):
|
|
def __init__(self, coords, vector, color):
|
|
self.coords = [float(x) for x in coords]
|
|
self.vector = vector
|
|
self.trails = False
|
|
self.last_coords = None
|
|
self.color = color
|
|
def move(self):
|
|
self.last_coords = [x for x in self.coords]
|
|
offset = self.vector.resolve()
|
|
self.coords[0] += offset[0]
|
|
self.coords[1] += offset[1]
|
|
def draw(self):
|
|
lc = scale_for_screen(self.last_coords)
|
|
c = scale_for_screen(self.coords)
|
|
scr.lock()
|
|
if not trails:
|
|
if lc:
|
|
pygame.draw.circle(scr, (0,0,0), lc, 2, 1)
|
|
pygame.draw.circle(scr, self.color, c, 2, 1)
|
|
scr.unlock()
|
|
|
|
|
|
|
|
scale = 1.0
|
|
def scale_for_screen(coords):
|
|
if not coords:
|
|
return None
|
|
|
|
x, y = coords
|
|
x, y = [x - origin_x, y - origin_y]
|
|
x, y = [x * scale, y * scale]
|
|
x, y = [x + origin_x, y + origin_y]
|
|
return [int(x), int(y)]
|
|
|
|
class GravityEmitter(GravitySlave):
|
|
def __init__(self, coords=[0,0], vector=Vector(0,0), mass=1, color=(255,255,255)):
|
|
GravitySlave.__init__(self, coords, vector, color)
|
|
self.mass = float(mass)
|
|
|
|
|
|
def vectorize(self, coords):
|
|
coords = [float(x) for x in coords]
|
|
xdist = -coords[0] + self.coords[0]
|
|
ydist = -coords[1] + self.coords[1]
|
|
dist_sqr = (xdist**2 + ydist**2)
|
|
mag = self.mass * (grav_const * 10**-5) / dist_sqr
|
|
mag = mag * 8.64**2 * 10**-1
|
|
dir = xy2dir([xdist, ydist])
|
|
return Vector(dir, mag)
|
|
|
|
|
|
|
|
def apply_emitters(slave):
|
|
for emit in emitters:
|
|
if id(emit) != id(slave):
|
|
slave.vector += emit.vectorize(slave.coords)
|
|
def apply_all_emitters():
|
|
for slave in slaves:
|
|
apply_emitters(slave)
|
|
|
|
if __name__ == '__main__':
|
|
pygame.init()
|
|
|
|
dir_player = math.pi
|
|
|
|
size = width, height = (800,600)
|
|
scr = pygame.display.set_mode(size)
|
|
|
|
#options
|
|
color_player = (255,255,255)
|
|
bounce = False
|
|
speed_player = 5.0
|
|
trails = False
|
|
|
|
scr.fill((0,0,0))
|
|
|
|
keys = []
|
|
origin_x = 400.0
|
|
origin_y = 300.0
|
|
earth = GravityEmitter(coords=[origin_x - 147.098074, origin_y],
|
|
mass=5.9742,
|
|
vector=Vector(math.pi, 2.616797),
|
|
color=(32,32,255)
|
|
)
|
|
mars = GravityEmitter(coords=[origin_x + 249.228730, origin_y],
|
|
mass=0.64185,
|
|
vector=Vector(0, 1.8983808),
|
|
color=(220,0,0)
|
|
)
|
|
venus = GravityEmitter(coords=[origin_x, origin_y + 108.941849],
|
|
mass=4.8685,
|
|
vector=Vector(math.pi/2, 3.0053376),
|
|
color=(255,255,180)
|
|
)
|
|
merc = GravityEmitter(coords=[origin_x, origin_y - 69.817079],
|
|
mass=0.3302,
|
|
vector=Vector(math.pi*3/2, 3.357504),
|
|
color=(255,120,0)
|
|
)
|
|
|
|
sun = GravityEmitter(coords=[origin_x, origin_y],
|
|
mass=1989100,
|
|
color=(255,255,32)
|
|
)
|
|
evilsun = GravityEmitter(coords=[800.0, 600.0],
|
|
mass=989100,
|
|
color=(120,120,120),
|
|
vector=Vector(math.pi*3/16, 1.623)
|
|
)
|
|
slaves = [earth, sun, mars, venus, merc]
|
|
emitters = [x for x in slaves if type(x) == GravityEmitter]
|
|
lock = None
|
|
|
|
while True:
|
|
events = pygame.event.get((KEYDOWN, KEYUP))
|
|
for ev in events:
|
|
if ev.type == KEYUP:
|
|
try:
|
|
del keys[keys.index(ev.key)]
|
|
except IndexError:
|
|
pass
|
|
else:
|
|
handle_key_ev(ev.key)
|
|
keys += [ev.key]
|
|
|
|
|
|
handle_keys(keys)
|
|
pygame.event.pump()
|
|
|
|
if not pause:
|
|
#ball.trails = trails
|
|
apply_all_emitters()
|
|
for o in slaves:
|
|
o.move()
|
|
|
|
if lock != None:
|
|
lv = Vector(lock.vector.dir, lock.vector.mag)
|
|
lc = [origin_x - lock.coords[0], origin_y - lock.coords[1]]
|
|
for o in slaves:
|
|
o.vector = o.vector - lv
|
|
o.coords[0] += lc[0]
|
|
o.coords[1] += lc[1]
|
|
|
|
for o in slaves:
|
|
o.draw()
|
|
|
|
pygame.display.flip()
|