pass
def draw(self, surf):
- pygame.draw.rect(surf, BLACK, pygame.Rect(self.left, self.top, self.width, self.height), self.line_thickness)
+ pygame.draw.rect(surf, GRAY, pygame.Rect(self.left, self.top, self.width, self.height), self.line_thickness)
from pygame import Vector2
+from itertools import combinations
def handleBoxCollision(particle, box): # Discrete Collision Detection
particle1.velocity = v1_prime
particle2.velocity = v2_prime
+
+
+def sweepAndPrune(particle_list):
+ particles = particle_list.copy()
+
+ particles.sort(key=lambda x: x.position.x)
+ x_checks = []
+ active = [particles[0]]
+ for particle in particles:
+ if particle == active[0]:
+ continue
+
+ start_x = active[-1].position.x - active[-1].radius
+ end_x = active[-1].position.x + active[-1].radius
+ if (start_x <= particle.position.x - particle.radius <= end_x or
+ start_x <= particle.position.x <= end_x or
+ start_x <= particle.position.x + particle.radius <= end_x):
+ active.append(particle)
+ if len(active) > 1:
+ x_checks.extend(tuple(combinations(active, 2)))
+ active = [particle]
+
+ particles.sort(key=lambda x: x.position.y)
+ y_checks = []
+ active = [particles[0]]
+ for particle in particles:
+ if particle == active[0]:
+ continue
+ start_y = active[-1].position.y - active[-1].radius
+ end_y = active[-1].position.y + active[-1].radius
+ if (start_y <= particle.position.y - particle.radius <= end_y or
+ start_y <= particle.position.y <= end_y or
+ start_y <= particle.position.y + particle.radius <= end_y):
+ active.append(particle)
+ if len(active) > 1:
+ y_checks.extend(tuple(combinations(active, 2)))
+ active = [particle]
+
+ return remove_duplicates(x_checks, y_checks)
+
+
+def intersection(arr1, arr2):
+ return [value for value in arr1 if value in set(arr2)]
+
+
+def remove_duplicates(arr1, arr2):
+ return list(set(arr1 + arr2))
from box import Box
from colours import *
from particle import Particle
+from collision import sweepAndPrune, handleParticleCollision
pygame.init()
self.collision_objects = {layer: [] for layer in range(self.COLLISION_LAYERS)}
self.particles = []
- n = 5
- for i in range(1, n):
- for j in range(1, n):
- m = random.randint(35, 45)
+ rows = 10
+ cols = 10
+
+ w, h = self.WIDTH / cols, self.HEIGHT / rows
+
+ for i in range(1, 1 + cols):
+ for j in range(1, 1 + rows):
+ r = random.randint(10, 30)
speed = 0.1
- self.particles.append(Particle((self.WIDTH / n * i, self.HEIGHT / n * j),
+ self.particles.append(Particle((w * i - w / 2, h * j - h / 2),
((random.random() - 0.5) * speed, (random.random() - 0.5) * speed),
- (0, 0), m, 100, self.collision_objects[0]))
+ (0, 0), r, r ** 2 * 3.14, self.collision_objects[0]))
self.box = Box((0, 0), self.WIDTH, self.HEIGHT)
- self.collision_objects[0] += self.particles
self.collision_objects[0].append(self.box)
+ self.collided_last_frame = set()
+
def show(self):
screen = pygame.display.set_mode(self.DIMENSIONS)
clock = pygame.time.Clock()
while self.is_running:
self.update(delta)
self.draw(screen)
- pygame.display.flip()
- delta = clock.tick(self.FPS)
- print(delta)
+ pygame.display.update()
+ delta = clock.tick()
+ # print(delta)
pygame.quit()
def update(self, delta):
for particle in self.particles:
particle.update(delta)
+ for particle1, particle2 in sweepAndPrune(self.particles):
+ if (particle1, particle2) not in self.collided_last_frame and (
+ particle2, particle1) not in self.collided_last_frame:
+ handleParticleCollision(particle1, particle2)
+
+ self.collided_last_frame.add((particle1, particle2))
+ self.collided_last_frame.add((particle2, particle1))
+
+ if particle1.position.distance_to(particle2.position) > particle1.radius + particle2.radius and \
+ particle1 != particle2:
+ self.collided_last_frame.remove((particle1, particle2))
+ self.collided_last_frame.remove((particle2, particle1))
+
def draw(self, surf):
- surf.fill(WHITE)
+ surf.fill(BLACK)
self.box.draw(surf)
for particle in self.particles:
particle.draw(surf)
+
+ for p1, p2 in sweepAndPrune(self.particles):
+ pygame.draw.line(surf, GREEN, p1.position, p2.position, 3)
self.collision_layer = collision_layer
+ self.colour = RED
+
+
def get_next_frame(self, position, velocity, delta):
vel = pygame.Vector2()
pos = pygame.Vector2()
self.top = self.position.y - self.radius
self.bottom = self.position.y + self.radius
- for thing in self.collision_layer:
- if isinstance(thing, Box):
- handleBoxCollision(self, thing)
- elif isinstance(thing, Particle):
- handleParticleCollision(self, thing)
+ handleBoxCollision(self, self.collision_layer[0])
def draw(self, surf):
- pygame.draw.circle(surf, RED, self.position, self.radius)
+ pygame.draw.circle(surf, self.colour, self.position, self.radius)