From: Skullheadx Date: Thu, 26 Jan 2023 21:57:06 +0000 (-0500) Subject: reverted to old way + split wall collision X-Git-Url: http://git.skullheadx.com/nixos/static/git-favicon.png?a=commitdiff_plain;h=07b95d45d79acd9f9cbbeec4de71763b28c3c833;p=Collision-Simulation.git reverted to old way + split wall collision --- diff --git a/collision.py b/collision.py index 5d94970..f28028a 100644 --- a/collision.py +++ b/collision.py @@ -1,65 +1,104 @@ -import numpy as np from pygame import Vector2 -from math import sqrt from itertools import combinations -def handleBoxCollision(particle, box): # Discrete Collision Detection - if particle.left <= box.left or particle.right >= box.right: - particle.velocity.x *= -1 - if particle.bottom >= box.bottom or particle.top <= box.top: +def detectTopCollision(particle, box): + if particle.top <= box.top: + return True + return False + + +def detectBottomCollision(particle, box): + if particle.bottom >= box.bottom: + return True + return False + + +def detectLeftCollision(particle, box): + if particle.left <= box.left: + return True + return False + + +def detectRightCollision(particle, box): + if particle.right >= box.right: + return True + return False + + +def handleTopCollision(particle, box): + particle.velocity.y *= -1 + # particle.position.y = box.top + particle.radius + return True + + +def handleBottomCollision(particle, box): + particle.velocity.y *= -1 + # particle.position.y = box.bottom - particle.radius + return True + + +def handleLeftCollision(particle, box): + particle.velocity.x *= -1 + # particle.position.x = box.left + particle.radius + return True + + +def handleRightCollision(particle, box): + particle.velocity.x *= -1 + # particle.position.x = box.right - particle.radius + return True + + +def handleBoxCollision(particle, box): + if detectTopCollision(particle, box) or detectBottomCollision(particle, box): particle.velocity.y *= -1 + return True + elif detectLeftCollision(particle, box) or detectRightCollision(particle, box): + particle.velocity.x *= -1 + return True + return False -def handleParticleCollision(particle1, particle2): # https://www.vobarian.com/collisions/2dcollisions2.pdf +def detectParticleCollision(particle1, particle2): if particle1.position.distance_to(particle2.position) <= particle1.radius + particle2.radius and \ particle1 != particle2: + return True + return False + + +def handleParticleCollision(particle1, particle2): # https://www.vobarian.com/collisions/2dcollisions2.pdf + if detectParticleCollision(particle1, particle2): + n = particle2.position - particle1.position + un = n / n.magnitude() + ut = Vector2(-un.y, un.x) + + v1 = particle1.velocity + v2 = particle2.velocity + + v1n = un.dot(v1) + v1t = ut.dot(v1) + v2n = un.dot(v2) + v2t = ut.dot(v2) + + v1t_prime = v1t + v2t_prime = v2t + + v1n_prime = (v1n * (particle1.mass - particle2.mass) + 2 * particle2.mass * v2n) / ( + particle1.mass + particle2.mass) + v2n_prime = (v2n * (particle2.mass - particle1.mass) + 2 * particle1.mass * v1n) / ( + particle1.mass + particle2.mass) + + v1_prime = v1n_prime * un + v1t_prime * ut + v2_prime = v2n_prime * un + v2t_prime * ut + + particle1.velocity = v1_prime + particle2.velocity = v2_prime + return True + return False + - v1 = np.array(particle1.velocity) - v2 = np.array(particle2.velocity) - x1 = np.array(particle1.position) - x2 = np.array(particle2.position) - m1 = particle1.mass - m2 = particle2.mass - - v1 = v1 - (2 * m2 / (m1 + m2)) * np.dot(v1 - v2, x1 - x2) / np.linalg.norm(x1 - x2) ** 2 * (x1 - x2) - v2 = v2 - (2 * m1 / (m1 + m2)) * np.dot(v2 - v1, x2 - x1) / np.linalg.norm(x2 - x1) ** 2 * (x2 - x1) - - particle1.velocity = Vector2(list(v1)) - particle2.velocity = Vector2(list(v2)) - - # v1 - (2 * m2 / (m1 + m2)) * np.dot(v1 - v2, x1 - x2) / np.linalg.norm(x1 - x2) ** 2 * (x1 - x2) - # particle1.velocity = particle1.velocity - (2 * particle2.mass) / (particle1.mass + particle2.mass) * (particle1.velocity - particle2.velocity).dot(particle1.position - particle2.position) / ((particle1.position - particle2.position).normalize() * (particle1.position - particle2.position).normalize()) * (particle1.position - particle2.position) - # particle2.velocity = particle2.velocity - (2 * particle1.mass) / (particle1.mass + particle2.mass) * (particle2.velocity - particle1.velocity).dot(particle2.position - particle1.position) / ((particle2.position - particle1.position).normalize() * (particle2.position - particle1.position).normalize()) * (particle2.position - particle1.position) - - # n = particle2.position - particle1.position - # un = n / n.magnitude() - # ut = Vector2(-un.y, un.x) - # - # v1 = particle1.velocity - # v2 = particle2.velocity - # - # v1n = un.dot(v1) - # v1t = ut.dot(v1) - # v2n = un.dot(v2) - # v2t = ut.dot(v2) - # - # v1t_prime = v1t - # v2t_prime = v2t - # - # v1n_prime = (v1n * (particle1.mass - particle2.mass) + 2 * particle2.mass * v2n) / ( - # particle1.mass + particle2.mass) - # v2n_prime = (v2n * (particle2.mass - particle1.mass) + 2 * particle1.mass * v1n) / ( - # particle1.mass + particle2.mass) - # - # v1_prime = v1n_prime * un + v1t_prime * ut - # v2_prime = v2n_prime * un + v2t_prime * ut - # - # particle1.velocity = v1_prime - # particle2.velocity = v2_prime - - -def sweepAndPrune(particle_list): +def sweepAndPrune(particle_list): # broad phase collision detection particles = particle_list.copy() particles.sort(key=lambda x: x.position.x) diff --git a/display.py b/display.py index acda743..0de96b5 100644 --- a/display.py +++ b/display.py @@ -4,7 +4,7 @@ import random from box import Box from colours import * from particle import Particle -from collision import sweepAndPrune, handleParticleCollision +from collision import sweepAndPrune, handleParticleCollision, detectParticleCollision pygame.init() @@ -33,7 +33,7 @@ class Display: for i in range(1, 1 + cols): for j in range(1, 1 + rows): r = random.randint(10, 30) - speed = 0.1 + speed = 0.5 self.particles.append(Particle((w * i - w / 2, h * j - h / 2), ((random.random() - 0.5) * speed, (random.random() - 0.5) * speed), (0, 0), r, r ** 2 * 3.14, self.collision_objects[0])) @@ -75,8 +75,7 @@ class Display: 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: + if not detectParticleCollision(particle1, particle2): self.collided_last_frame.remove((particle1, particle2)) self.collided_last_frame.remove((particle2, particle1)) diff --git a/particle.py b/particle.py index 8cb7390..6619b74 100644 --- a/particle.py +++ b/particle.py @@ -3,10 +3,13 @@ from math import copysign import pygame from box import Box -from collision import handleBoxCollision, handleParticleCollision +from collision import handleBoxCollision, handleParticleCollision, detectTopCollision, handleTopCollision, \ + detectBottomCollision, handleBottomCollision, detectLeftCollision, handleLeftCollision, handleRightCollision, \ + detectRightCollision from colours import * + class Particle: speed_limit = 3 @@ -26,6 +29,8 @@ class Particle: self.colour = RED + self.collided_with_wall = {"top":False, "bottom": False, "left": False, "right": False} + def get_next_frame(self, position, velocity, delta): vel = pygame.Vector2() @@ -49,7 +54,30 @@ class Particle: self.top = self.position.y - self.radius self.bottom = self.position.y + self.radius - handleBoxCollision(self, self.collision_layer[0]) + if not self.collided_with_wall["top"] and detectTopCollision(self, self.collision_layer[0]): + handleTopCollision(self, self.collision_layer[0]) + self.collided_with_wall["top"] = True + if not detectTopCollision(self, self.collision_layer[0]): + self.collided_with_wall["top"] = False + + if not self.collided_with_wall["bottom"] and detectBottomCollision(self, self.collision_layer[0]): + handleBottomCollision(self, self.collision_layer[0]) + self.collided_with_wall["bottom"] = True + if not detectBottomCollision(self, self.collision_layer[0]): + self.collided_with_wall["bottom"] = False + + if not self.collided_with_wall["left"] and detectLeftCollision(self, self.collision_layer[0]): + handleLeftCollision(self, self.collision_layer[0]) + self.collided_with_wall["left"] = True + if not detectLeftCollision(self, self.collision_layer[0]): + self.collided_with_wall["left"] = False + + if not self.collided_with_wall["right"] and detectRightCollision(self, self.collision_layer[0]): + handleRightCollision(self, self.collision_layer[0]) + self.collided_with_wall["right"] = True + if not detectRightCollision(self, self.collision_layer[0]): + self.collided_with_wall["right"] = False + def draw(self, surf): pygame.draw.circle(surf, self.colour, self.position, self.radius)