def _bounce_one(a1, a2): # Bounces a1 dir_angle = vectors.angle(a2.pos, a1.pos) vel_angle = vectors.angle(a1.velocity) # If they are head on then we want to swivel them a little if vectors.bound_angle(dir_angle[0] + 180) == vel_angle[0]: dir_angle[0] = vectors.bound_angle(dir_angle[0] + 40) # Keep trying distances further and further apart until they're # not going to be overlapping any more overlapping = True dist = vectors.total_velocity(a1.velocity) a2_rect = (a2.pos[0], a2.pos[1], a2.size[0], a2.size[1]) while overlapping: new_pos = vectors.add_vectors(a1.pos, vectors.move_to_vector(dir_angle, dist)) new_rect = (new_pos[0], new_pos[1], a1.size[0], a1.size[1]) if not geometry.rect_collision(new_rect, a2_rect, True): overlapping = False dist += 1 # Add a bit to be safe new_pos = vectors.add_vectors( a1.pos, vectors.move_to_vector(dir_angle, dist + vectors.total_velocity(a1.velocity))) a1.pos = new_pos
def _bounce_one(a1, a2): # Bounces a1 dir_angle = vectors.angle(a2.pos, a1.pos) vel_angle = vectors.angle(a1.velocity) # If they are head on then we want to swivel them a little if vectors.bound_angle(dir_angle[0]+180) == vel_angle[0]: dir_angle[0] = vectors.bound_angle(dir_angle[0] + 40) # Keep trying distances further and further apart until they're # not going to be overlapping any more overlapping = True dist = vectors.total_velocity(a1.velocity) a2_rect = (a2.pos[0], a2.pos[1], a2.size[0], a2.size[1]) while overlapping: new_pos = vectors.add_vectors(a1.pos, vectors.move_to_vector( dir_angle, dist )) new_rect = (new_pos[0], new_pos[1], a1.size[0], a1.size[1]) if not geometry.rect_collision(new_rect, a2_rect, True): overlapping = False dist += 1 # Add a bit to be safe new_pos = vectors.add_vectors(a1.pos, vectors.move_to_vector( dir_angle, dist + vectors.total_velocity(a1.velocity) )) a1.pos = new_pos
def test_possible_collision(actors, new_rect, convert=True): """ Used to test if a potential actor will collide with anything else returns True if there will be a collision """ for a in actors: if geometry.rect_collision(a.rect, new_rect, convert): return True return False
def _will_collide(a1, a2, target=None): """Answers if a2 will collide with a1's movement target""" if not target: target = a1.current_action()[1] target_rect = pygame.Rect((0, 0, a1.rect.width, a1.rect.height)) target_rect.left = target[0] - a1.rect.width / 2 target_rect.top = target[1] - a1.rect.height / 2 return geometry.rect_collision(target_rect, a2.rect, convert=True)
def _will_collide(a1, a2, target=None): """Answers if a2 will collide with a1's movement target""" if not target: target = a1.current_action()[1] target_rect = pygame.Rect((0, 0, a1.rect.width, a1.rect.height)) target_rect.left = target[0] - a1.rect.width/2 target_rect.top = target[1] - a1.rect.height/2 return geometry.rect_collision(target_rect, a2.rect, convert=True)
def get_collisions(actors): collisions = [] collided = set() for i, a in enumerate(actors): for j, b in enumerate(actors): if j in collided: continue if i == j: continue if geometry.rect_collision(a.rect, b.rect, True): collisions.append((a,b)) collided.add(i) return collisions
def _bounce_both(a1, a2): # These are the angles directly away from each other angle1 = vectors.angle(a2.pos, a1.pos) angle2 = vectors.angle(a1.pos, a2.pos) vel_angle1 = vectors.angle(a1.velocity) vel_angle2 = vectors.angle(a2.velocity) # If they are head on then we want to swivel them a little if vel_angle1[0] == angle2[0] and vel_angle2[0] == angle1[0]: angle1[0] = vectors.bound_angle(angle1[0] + 20) angle2[0] = vectors.bound_angle(angle2[0] + 20) # Keep trying distances further and further apart until they're # not going to be overlapping any more overlapping = True dist_multiplier = 0.1 while overlapping: dist_multiplier += 0.1 new_pos1 = vectors.add_vectors( a1.pos, vectors.move_to_vector(angle1, max(a1.size) * dist_multiplier)) new_pos2 = vectors.add_vectors( a2.pos, vectors.move_to_vector(angle2, max(a2.size) * dist_multiplier)) new_rect1 = (new_pos1[0], new_pos1[1], a1.size[0], a1.size[1]) new_rect2 = (new_pos2[0], new_pos2[1], a2.size[0], a2.size[1]) if not geometry.rect_collision(new_rect1, new_rect2): overlapping = False a1.pos = new_pos1 a2.pos = new_pos2
def _bounce_both(a1, a2): # These are the angles directly away from each other angle1 = vectors.angle(a2.pos, a1.pos) angle2 = vectors.angle(a1.pos, a2.pos) vel_angle1 = vectors.angle(a1.velocity) vel_angle2 = vectors.angle(a2.velocity) # If they are head on then we want to swivel them a little if vel_angle1[0] == angle2[0] and vel_angle2[0] == angle1[0]: angle1[0] = vectors.bound_angle(angle1[0] + 20) angle2[0] = vectors.bound_angle(angle2[0] + 20) # Keep trying distances further and further apart until they're # not going to be overlapping any more overlapping = True dist_multiplier = 0.1 while overlapping: dist_multiplier += 0.1 new_pos1 = vectors.add_vectors(a1.pos, vectors.move_to_vector( angle1, max(a1.size) * dist_multiplier )) new_pos2 = vectors.add_vectors(a2.pos, vectors.move_to_vector( angle2, max(a2.size) * dist_multiplier )) new_rect1 = (new_pos1[0], new_pos1[1], a1.size[0], a1.size[1]) new_rect2 = (new_pos2[0], new_pos2[1], a2.size[0], a2.size[1]) if not geometry.rect_collision(new_rect1, new_rect2): overlapping = False a1.pos = new_pos1 a2.pos = new_pos2
def test_rectangle_collision(self): vals = ( # R1 is up and to the left of R2 ((5, 5, 15, 15), (10, 10, 20, 20), True), ((2, 2, 8, 8), (10, 10, 20, 20), False), # R1 is up of R2 ((10, 5, 20, 15), (10, 10, 20, 20), True), ((10, 2, 20, 8), (10, 10, 20, 20), False), # R1 is up and to the right of R2 ((15, 5, 25, 15), (10, 10, 20, 20), True), ((15, 2, 25, 8), (10, 10, 20, 20), False), # R1 is left of R2 ((5, 10, 15, 20), (10, 10, 20, 20), True), ((2, 10, 8, 20), (10, 10, 20, 20), False), # R1 is right of R2 ((15, 10, 25, 20), (10, 10, 20, 20), True), ((25, 10, 30, 20), (10, 10, 20, 20), False), # R1 is down and to the left of R2 ((5, 15, 15, 25), (10, 10, 20, 20), True), ((2, 15, 8, 25), (10, 10, 20, 20), False), # R1 is down of R2 ((10, 15, 20, 25), (10, 10, 20, 20), True), ((10, 22, 20, 28), (10, 10, 20, 20), False), # R1 is down and to the right of R2 ((15, 15, 25, 25), (10, 10, 20, 20), True), ((22, 15, 28, 25), (10, 10, 20, 20), False), # Overlapping ((15, 15, 25, 25), (15, 15, 25, 25), True),# Exact same size ((279, 779, 279+41, 779+41), (279, 779, 279+41, 779+41), True),# Exact same size ((394, 79, 435, 435), (317, 79, 358, 120), False), ((10, 10, 30, 30), (15, 15, 25, 25), True),# R1 is bigger ((15, 15, 25, 25), (10, 10, 30, 30), True),# R2 is bigger # Different types ((5, 15, 15, 25), pygame.Rect(10, 10, 20, 20), True), ((2, 15, 8, 25), pygame.Rect(10, 10, 20, 20), False), ) for r1, r2, expected in vals: # We want to make sure that it'll work for inputs regardless of order try: self.assertEqual(expected, geometry.rect_collision(r1, r2)) except Exception as e: print("Failed on first pass of %s, %s" % (str(r1), str(r2))) raise try: self.assertEqual(expected, geometry.rect_collision(r2, r1)) except Exception as e: print("Failed on second pass of %s, %s" % (str(r1), str(r2))) raise