-
Notifications
You must be signed in to change notification settings - Fork 12
Expand file tree
/
Copy pathuniverse.py
More file actions
121 lines (94 loc) · 3.65 KB
/
Copy pathuniverse.py
File metadata and controls
121 lines (94 loc) · 3.65 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
import math,random,pygame
from pygame.locals import *
def combineVectors(vector1, vector2):
""" Adds together two vectors given as an angle plus a magnitude (length)"""
(angle1, length1) = vector1
(angle2, length2) = vector2
x = math.sin(angle1) * length1
y = math.cos(angle1) * length1
x1 = x + math.sin(angle2) * length2
y1 = y + math.cos(angle2) * length2
angle = 0.5*math.pi - math.atan2(y1, x1)
length = math.hypot(x1, y1)
return (angle, length)
class Particle():
def __init__(self, x, y, mass=1):
self.x = x
self.y = y
self.mass = mass
self.findRadius()
self.speed = 0
self.angle = 0
def findRadius(self):
self.radius = 0.4 * self.mass ** (1.0/3.0)
self.size = int(self.radius)
if self.size < 2:
self.colour = (100+self.mass, 100+self.mass, 100+self.mass)
else:
self.colour = (255,255, 0)
def move(self):
""" Moves the particle based on its speed and direction """
self.x += math.sin(self.angle) * self.speed
self.y += math.cos(self.angle) * self.speed
def attract(self, other):
"""" Particles attract one another based on their distance and masses"""
dx = (self.x - other.x) * 2
dy = (self.y - other.y) * 2
dist = math.hypot(dx, dy)
force = 0.1 * self.mass * other.mass / dist**2
theta = 0.5 * math.pi - math.atan2(dy, dx)
if dist < self.radius + other.radius:
total_mass = self.mass + other.mass
self.x = (self.x * self.mass + other.x * other.mass) / total_mass
self.y = (self.y * self.mass + other.y * other.mass) / total_mass
self.speed = self.speed * self.mass / total_mass
other.speed = other.speed * other.mass / total_mass
(self.angle, self.speed) = combineVectors((self.angle, self.speed), (other.angle, other.speed))
self.mass = total_mass
self.findRadius()
return other
else:
(self.angle, self.speed) = combineVectors((self.angle, self.speed), (theta+math.pi, force/self.mass))
(other.angle, other.speed) = combineVectors((other.angle, other.speed), (theta, force/other.mass))
# Set up Pygame variables
pygame.init()
BG_colour = (0,0,0)
particle_colour = (200,200,200)
(width, height) = (480, 360)
screen = pygame.display.set_mode((width, height))
number_of_particles = 170
particles = []
for p in range(number_of_particles):
mass = random.randint(1, 4)
#mass = 1
x = random.randrange(0, width)
y = random.randrange(0, height)
particles.append(Particle(x, y, mass))
running = True
while running:
for event in pygame.event.get():
if event.type == QUIT:
running = False
screen.fill(BG_colour)
for i in range(number_of_particles):
j = i+1
while j < number_of_particles:
collide = particles[i].attract(particles[j])
if collide != None:
particles.remove(collide)
number_of_particles -= 1
else:
j += 1
for p in particles:
p.move()
# if p.size < 1:
# screen.set_at((int(p.x), int(p.y)), particle_colour)
if p.size < 2:
pygame.draw.rect(screen, p.colour, (int(p.x), int(p.y), 2, 2))
else:
pygame.draw.circle(screen, p.colour, (int(p.x), int(p.y)), p.size, 0)
pygame.display.flip()
for p in particles:
dx = math.sin(p.angle) * p.speed
dy = math.cos(p.angle) * p.speed
print ("(%d, %d)\t(dx=%f, dy=%f)\tmass = %d" % (p.x, p.y, dx, dy, p.mass))