-
Notifications
You must be signed in to change notification settings - Fork 12
/
Copy pathcollision.py
135 lines (108 loc) · 3.84 KB
/
collision.py
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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
import pygame, random, math
background_colour = (255,255,255)
(width, height) = (400, 400)
drag = 0.9999
elasticity = 0.75
gravity = (math.pi, 0.1)
def addVectors(vector1, vector2):
(angle1, length1) = vector1
(angle2, length2) = vector2
x = math.sin(angle1) * length1 + math.sin(angle2) * length2
y = math.cos(angle1) * length1 + math.cos(angle2) * length2
angle = 0.5 * math.pi - math.atan2(y, x)
length = math.hypot(x, y)
return (angle, length)
def findParticle(particles, x, y):
for p in particles:
if math.hypot(p.x-x, p.y-y) <= p.size:
return p
return None
def collide(p1, p2):
dx = p1.x - p2.x
dy = p1.y - p2.y
dist = math.hypot(dx, dy)
if dist < p1.size + p2.size:
tangent = math.atan2(dy, dx)
p1.angle = 2*tangent - p1.angle
p2.angle = 2*tangent - p2.angle
(p1.speed, p2.speed) = (p2.speed, p1.speed)
p1.speed *= elasticity
p2.speed *= elasticity
angle = 0.5 * math.pi + tangent
p1.x += math.sin(angle)
p1.y -= math.cos(angle)
p2.x -= math.sin(angle)
p2.y += math.cos(angle)
class Particle():
def __init__(self, x_y, size):
(x, y) = x_y
self.x = x
self.y = y
self.size = size
self.colour = (0, 0, 255)
self.thickness = 0
self.speed = 0
self.angle = 0
def display(self):
pygame.draw.circle(screen, self.colour, (int(self.x), int(self.y)), self.size, self.thickness)
def move(self):
(self.angle, self.speed) = addVectors((self.angle, self.speed), gravity)
self.x += math.sin(self.angle) * self.speed
self.y -= math.cos(self.angle) * self.speed
self.speed *= drag
def bounce(self):
if self.x > width - self.size:
self.x = 2*(width - self.size) - self.x
self.angle = - self.angle
self.speed *= elasticity
elif self.x < self.size:
self.x = 2*self.size - self.x
self.angle = - self.angle
self.speed *= elasticity
if self.y > height - self.size:
self.y = 2*(height - self.size) - self.y
self.angle = math.pi - self.angle
self.speed *= elasticity
elif self.y < self.size:
self.y = 2*self.size - self.y
self.angle = math.pi - self.angle
self.speed *= elasticity
screen = pygame.display.set_mode((width, height))
pygame.display.set_caption('Tutorial 8')
number_of_particles = 5
my_particles = []
for n in range(number_of_particles):
size = random.randint(10, 20)
x = random.randint(size, width-size)
y = random.randint(size, height-size)
particle = Particle((x, y), size)
particle.speed = random.random()*10
particle.angle = random.uniform(0, math.pi*2)
my_particles.append(particle)
selected_particle = None
running = True
clock = pygame.time.Clock()
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.MOUSEBUTTONDOWN:
(mouseX, mouseY) = pygame.mouse.get_pos()
selected_particle = findParticle(my_particles, mouseX, mouseY)
elif event.type == pygame.MOUSEBUTTONUP:
selected_particle = None
if selected_particle:
(mouseX, mouseY) = pygame.mouse.get_pos()
dx = mouseX - selected_particle.x
dy = mouseY - selected_particle.y
selected_particle.angle = 0.5*math.pi + math.atan2(dy, dx)
selected_particle.speed = math.hypot(dx, dy) * 0.1
screen.fill(background_colour)
for i, particle in enumerate(my_particles):
particle.move()
particle.bounce()
for particle2 in my_particles[i+1:]:
collide(particle, particle2)
particle.display()
pygame.display.flip()
clock.tick(50)