Example #1
0
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
Example #2
0
    def _accelerate_ai(self, target):
        dist = vectors.distance(self.pos, target)

        if dist > self.max_velocity:
            self.velocity = vectors.move_to_vector(vectors.angle(self.pos, target), self.max_velocity)
        else:
            self.velocity = vectors.move_to_vector(vectors.angle(self.pos, target), dist)
Example #3
0
    def generate_bullet(self, target):
        # Set correct origin
        offset_angle = vectors.bound_angle(
            vectors.add_vectors(self._effect_offset_angle, self.facing))

        origin_pos = vectors.add_vectors(
            self.get_offset_pos(use_effect_offset=True), self.actor.pos)

        # Get actual velocity we'll be using
        if type(target) == list or type(target) == tuple:
            direction = vectors.angle(origin_pos, target)
            target_pos = target
        else:
            direction = vectors.angle(origin_pos, target.pos)
            target_pos = target.pos

        velocity = vectors.move_to_vector(direction, self.bullet['velocity'])
        velocity[2] = math_lib.calc_trajectory(
            0.1, vectors.distance(origin_pos, target_pos),
            self.bullet['velocity'])

        the_bullet = bullets.Shell(
            pos=origin_pos,
            velocity=velocity,
            image=self.bullet['image'],
            size=self.bullet['size'],
            blast_radius=self.bullet['blast_radius'],
            damage=self.bullet['damage'],
            dissipation_func=self.bullet.get('dissipation_func', "linear"),
        )
        self.actor.bullets.append(the_bullet)
Example #4
0
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
Example #5
0
 def generate_bullet(self, target):
     # Set correct origin
     offset_angle = vectors.bound_angle(
         vectors.add_vectors(self._effect_offset_angle, self.facing)
     )
     
     origin_pos = vectors.add_vectors(self.get_offset_pos(use_effect_offset=True), self.actor.pos)
     
     # Get actual velocity we'll be using
     if type(target) == list or type(target) == tuple:
         direction = vectors.angle(origin_pos, target)
         target_pos = target
     else:
         direction = vectors.angle(origin_pos, target.pos)
         target_pos = target.pos
     
     velocity = vectors.move_to_vector(direction, self.bullet['velocity'])
     velocity[2] = math_lib.calc_trajectory(0.1, vectors.distance(origin_pos, target_pos), self.bullet['velocity'])
     
     the_bullet = bullets.Shell(
         pos=origin_pos,
         velocity=velocity,
         image = self.bullet['image'],
         size = self.bullet['size'],
         blast_radius = self.bullet['blast_radius'],
         damage = self.bullet['damage'],
         dissipation_func = self.bullet.get('dissipation_func', "linear"),
     )
     self.actor.bullets.append(the_bullet)
Example #6
0
    def _accelerate_ai(self, target):
        dist = vectors.distance(self.pos, target)

        if dist > self.max_velocity:
            self.velocity = vectors.move_to_vector(
                vectors.angle(self.pos, target), self.max_velocity)
        else:
            self.velocity = vectors.move_to_vector(
                vectors.angle(self.pos, target), dist)
Example #7
0
    def __init__(self, actor, ability_data={}):
        super(Ability, self).__init__()
        self.actor = actor
        self.facing = [0, 0]

        self.set_stats(ability_data)
        self.charge = self.required_charge

        self._effect_offset_distance = vectors.distance(self.effect_offset)
        self._effect_offset_angle = vectors.angle(self.effect_offset)

        self._img_offset_distance = vectors.distance(self.image_offset)
        self._img_offset_angle = vectors.angle(self.image_offset)
Example #8
0
 def __init__(self, actor, ability_data={}):
     super(Ability, self).__init__()
     self.actor = actor
     self.facing = [0,0]
     
     self.set_stats(ability_data)
     self.charge = self.required_charge
     
     self._effect_offset_distance = vectors.distance(self.effect_offset)
     self._effect_offset_angle = vectors.angle(self.effect_offset)
     
     self._img_offset_distance = vectors.distance(self.image_offset)
     self._img_offset_angle = vectors.angle(self.image_offset)
Example #9
0
    def can_use(self, target=None, **kwargs):
        """Called to see if the ability can be used"""
        if self.charge < self.required_charge:
            return False

        # Check aim
        if type(target) in (list, tuple):
            target_facing = vectors.angle(self.actor.pos, target)
        else:
            target_facing = vectors.angle(self.actor.pos, target.pos)

        if not self.check_aim(target_facing):
            return False

        return True
Example #10
0
 def can_use(self, target=None, **kwargs):
     """Called to see if the ability can be used"""
     if self.charge < self.required_charge:
         return False
     
     # Check aim
     if type(target) in (list, tuple):
         target_facing = vectors.angle(self.actor.pos, target)
     else:
         target_facing = vectors.angle(self.actor.pos, target.pos)
     
     if not self.check_aim(target_facing):
         return False
     
     return True
Example #11
0
 def run_ai(self):
     if self.micro_orders == []:
         cmd, pos, target = self.current_order
     else:
         cmd, pos, target = self.micro_orders[0]
     
     self._attack_ai()
     
     if cmd == "stop" or cmd == "hold position":
         self.velocity = [0,0,0]
         
         if target == 0:
             self.next_order()
     
     elif cmd == "move" or cmd == "reverse":
         dist = vectors.distance(self.pos, pos)
         self.velocity = vectors.move_to_vector(vectors.angle(self.pos, pos), self.max_velocity)
         
         if dist <= vectors.total_velocity(self.velocity):
             self.pos = pos
             self.velocity = [0,0,0]
             self.next_order()
         
     else:
         raise Exception("No handler for cmd %s (pos: %s, target: %s)" % (cmd, pos, target))
Example #12
0
    def test_angle_single(self):
        vals = (
            # XY Tests
            ([4, -4, 0], [45, 0]),  # Up and right
            ([4, 4, 0], [135, 0]),  # Down and right
            ([-4, 4, 0], [225, 0]),  # Down and left
            ([-4, -4, 0], [315, 0]),  # Up and left

            # Same as before but scaled up in size
            ([400, -400, 0], [45, 0]),  # Up and right
            ([1000, 1000, 0], [135, 0]),  # Down and right
            ([-0.5, 0.5, 0], [225, 0]),  # Down and left
            ([-50000, -50000, 0], [315, 0]),  # Up and left
            ([0, -4, 0], [0, 0]),  # Dead Up
            ([4, 0, 0], [90, 0]),  # Dead Right
            ([0, 4, 0], [180, 0]),  # Dead Down
            ([-4, 0, 0], [270, 0]),  # Dead Left
        )

        for a, expected in vals:
            r, r2 = vectors.angle(a)
            self.assertAlmostEqual(
                r,
                expected[0],
                places=2,
                msg="vectors.angle(%s) should equal %s, instead got %s" %
                (a, expected[0], r))
            self.assertAlmostEqual(r2, expected[1], places=2)
Example #13
0
 def __init__(self, filepath, columns=1, rows=1, animation_rate = 0.5, rotate_about=None):
     super(Animation, self).__init__()
     
     if columns < 1:
         raise Exception("Cannot have fewer than 1 column in an animation")
     
     if rows < 1:
         raise Exception("Cannot have fewer than 1 row in an animation")
     
     self.images = []
     self.animation_rate = animation_rate
     
     img = pygame.image.load(filepath)
     r = img.get_rect()
     
     # Break it down into tiles, save the tiles
     tile_width = r.width / columns
     tile_height = r.height / rows
     
     for y in range(rows):
         for x in range(columns):
             tile = pygame.Surface((tile_width, tile_height), SRCALPHA)
             tile.blit(img, (0,0), (x * tile_width, y * tile_height, tile_width, tile_height))
             
             self.images.append(tile)
     
     # Default the rotate about point
     if rotate_about == None:
         rotate_about = 0, 0, 0
     
     # centre_offset is a distance and angle
     self.centre_offset = (
         vectors.distance(rotate_about),
         vectors.angle(rotate_about),
     )
Example #14
0
 def test_angle_single(self):
     vals = (
         # XY Tests
         ([4,-4,0], [45, 0]),# Up and right
         ([4,4,0], [135, 0]),# Down and right
         ([-4,4,0], [225, 0]),# Down and left
         ([-4,-4,0], [315, 0]),# Up and left
         
         # Same as before but scaled up in size
         ([400,-400,0], [45, 0]),# Up and right
         ([1000,1000,0], [135, 0]),# Down and right
         ([-0.5,0.5,0], [225, 0]),# Down and left
         ([-50000,-50000,0], [315, 0]),# Up and left
         
         ([0,-4,0], [0, 0]),# Dead Up
         ([4,0,0], [90, 0]),# Dead Right
         ([0,4,0], [180, 0]),# Dead Down
         ([-4,0,0], [270, 0]),# Dead Left
     )
     
     for a, expected in vals:
         r, r2 = vectors.angle(a)
         self.assertAlmostEqual(r, expected[0], places=2, msg="vectors.angle(%s) should equal %s, instead got %s" % (
             a, expected[0], r
         ))
         self.assertAlmostEqual(r2, expected[1], places=2)
Example #15
0
 def generate_bullet(self, target):
     if type(target) == list or type(target) == tuple:
         direction = vectors.angle(self.actor.pos, target)
         target_pos = target
     else:
         direction = vectors.angle(self.actor.pos, target.pos)
         target_pos = target.pos
     
     velocity = vectors.move_to_vector(direction, self.bullet['velocity'])
     velocity[2] = math_lib.calc_trajectory(0.1, vectors.distance(self.actor.pos, target_pos), self.bullet['velocity'])
     
     the_bullet = bullets.Shell(
         pos=self.actor.pos,
         velocity=velocity,
         image = self.bullet['image'],
         size = self.bullet['size'],
         blast_radius = self.bullet['blast_radius'],
         damage = self.bullet['damage'],
         dissipation_func = self.bullet.get('dissipation_func', "linear"),
     )
     self.actor.bullets.append(the_bullet)
Example #16
0
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
Example #17
0
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
Example #18
0
    def _attack_ai(self):
        """AI handling the process of attacking"""

        target = self.get_first_target()

        if target == None:
            for a in self.abilities:
                a.turn(self.facing)
            return

        for a in self.abilities:
            # Turn the ability towards it's target
            a.turn(vectors.angle(self.pos, target.pos))

            if a.can_use(target):
                a.use(target)
Example #19
0
    def _attack_ai(self):
        """AI handling the process of attacking"""

        target = self.get_first_target()

        if target == None:
            for a in self.abilities:
                a.turn(self.facing)
            return

        for a in self.abilities:
            # Turn the ability towards it's target
            a.turn(vectors.angle(self.pos, target.pos))

            if a.can_use(target):
                a.use(target)
Example #20
0
    def __init__(self,
                 filepath,
                 columns=1,
                 rows=1,
                 animation_rate=0.5,
                 rotate_about=None):
        super(Animation, self).__init__()

        if columns < 1:
            raise Exception("Cannot have fewer than 1 column in an animation")

        if rows < 1:
            raise Exception("Cannot have fewer than 1 row in an animation")

        self.images = []
        self.animation_rate = animation_rate

        img = pygame.image.load(filepath)
        r = img.get_rect()

        # Break it down into tiles, save the tiles
        tile_width = r.width / columns
        tile_height = r.height / rows

        for y in range(rows):
            for x in range(columns):
                tile = pygame.Surface((tile_width, tile_height), SRCALPHA)
                tile.blit(
                    img, (0, 0),
                    (x * tile_width, y * tile_height, tile_width, tile_height))

                self.images.append(tile)

        # Default the rotate about point
        if rotate_about == None:
            rotate_about = 0, 0, 0

        # centre_offset is a distance and angle
        self.centre_offset = (
            vectors.distance(rotate_about),
            vectors.angle(rotate_about),
        )
Example #21
0
    def _turn_ai(self, target):
        self.facing = vectors.bound_angle(self.facing)

        target_angle = vectors.angle(self.pos, target)
        diff = vectors.angle_diff(self.facing, target_angle)[0]

        if abs(diff) <= self.turn_speed:
            self.facing = target_angle
            return True

        if diff < 0:
            self.facing[0] -= self.turn_speed
            for a in self.abilities:
                a.facing[0] += self.turn_speed
        else:
            self.facing[0] += self.turn_speed
            for a in self.abilities:
                a.facing[0] -= self.turn_speed

        return False
Example #22
0
    def _turn_ai(self, target):
        self.facing = vectors.bound_angle(self.facing)

        target_angle = vectors.angle(self.pos, target)
        diff = vectors.angle_diff(self.facing, target_angle)[0]

        if abs(diff) <= self.turn_speed:
            self.facing = target_angle
            return True

        if diff < 0:
            self.facing[0] -= self.turn_speed
            for a in self.abilities:
                a.facing[0] += self.turn_speed
        else:
            self.facing[0] += self.turn_speed
            for a in self.abilities:
                a.facing[0] -= self.turn_speed

        return False
Example #23
0
    def test_angle(self):
        vals = (
            # XY Tests
            ([0, 0, 0], [4, -4, 0], [45, 0]),  # Up and right
            ([0, 0, 0], [4, 4, 0], [135, 0]),  # Down and right
            ([0, 0, 0], [-4, 4, 0], [225, 0]),  # Down and left
            ([0, 0, 0], [-4, -4, 0], [315, 0]),  # Up and left

            # Same as before but scaled up in size
            ([0, 0, 0], [400, -400, 0], [45, 0]),  # Up and right
            ([0, 0, 0], [1000, 1000, 0], [135, 0]),  # Down and right
            ([0, 0, 0], [-0.5, 0.5, 0], [225, 0]),  # Down and left
            ([0, 0, 0], [-50000, -50000, 0], [315, 0]),  # Up and left
            ([0, 0, 0], [0, -4, 0], [0, 0]),  # Dead Up
            ([0, 0, 0], [4, 0, 0], [90, 0]),  # Dead Right
            ([0, 0, 0], [0, 4, 0], [180, 0]),  # Dead Down
            ([0, 0, 0], [-4, 0, 0], [270, 0]),  # Dead Left

            # Specific XY tests
            ([1, 1, 0], [4, 100, 0], [178.26,
                                      0]),  # Down and a little bit right
            ([400, 400, 0], [100, 900, 0], [210.963, 0]),  # Down and left

            # Z Tests
            # ([0,0,0], [4,-4,0], [0, 45]),# Aim up
            # ([0,0,0], [4,4,0], [135, 0]),# Aim down
            # ([0,0,0], [-4,4,0], [225, 0]),
            # ([0,0,0], [-4,-4,0], [315, 0]),
        )

        for a, b, expected in vals:
            r, r2 = vectors.angle(a, b)
            self.assertAlmostEqual(
                r,
                expected[0],
                places=2,
                msg="vectors.angle(%s, %s) should equal %s, instead got %s" %
                (a, b, expected[0], r))
            self.assertAlmostEqual(r2, expected[1], places=2)
Example #24
0
 def test_angle(self):
     vals = (
         # XY Tests
         ([0,0,0], [4,-4,0], [45, 0]),# Up and right
         ([0,0,0], [4,4,0], [135, 0]),# Down and right
         ([0,0,0], [-4,4,0], [225, 0]),# Down and left
         ([0,0,0], [-4,-4,0], [315, 0]),# Up and left
         
         # Same as before but scaled up in size
         ([0,0,0], [400,-400,0], [45, 0]),# Up and right
         ([0,0,0], [1000,1000,0], [135, 0]),# Down and right
         ([0,0,0], [-0.5,0.5,0], [225, 0]),# Down and left
         ([0,0,0], [-50000,-50000,0], [315, 0]),# Up and left
         
         ([0,0,0], [0,-4,0], [0, 0]),# Dead Up
         ([0,0,0], [4,0,0], [90, 0]),# Dead Right
         ([0,0,0], [0,4,0], [180, 0]),# Dead Down
         ([0,0,0], [-4,0,0], [270, 0]),# Dead Left
         
         # Specific XY tests
         ([1,1,0], [4,100,0], [178.26, 0]),# Down and a little bit right
         ([400, 400, 0], [100, 900, 0], [210.963,0]),# Down and left
         
         # Z Tests
         # ([0,0,0], [4,-4,0], [0, 45]),# Aim up
         # ([0,0,0], [4,4,0], [135, 0]),# Aim down
         # ([0,0,0], [-4,4,0], [225, 0]), 
         # ([0,0,0], [-4,-4,0], [315, 0]),
     )
     
     for a, b, expected in vals:
         r, r2 = vectors.angle(a, b)
         self.assertAlmostEqual(r, expected[0], places=2, msg="vectors.angle(%s, %s) should equal %s, instead got %s" % (
             a, b, expected[0], r
         ))
         self.assertAlmostEqual(r2, expected[1], places=2)
Example #25
0
class GeometryTests(unittest.TestCase):
    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
    
    # To generated these values I created a lot of triangles with different
    # positions for A, B and C to ensure a range of angles. I then used
    # https://github.com/Teifion/Mini-tools/blob/master/vectors.html
    # to calcuate the various raw angles and with pen+paper calcuated the
    # approximate angles and sizes. If the code was close then I knew
    # it was right as my workings had a lot of rounding errors, if it was
    # not close then something was wrong with either my paper workings
    # or the code.
    collision_vals = (
        # answers = A, B, C, a, b, c
        (([10,5,0], vectors.angle([3,1,0])), ([13,10,0], vectors.angle([2,-1,0])),
            (40.601, 94.398, 45.0,      5.366, 8.22, 5.83)),
        (([5,10,0], vectors.angle([3,-1,0])), ([10,1,0], vectors.angle([1,1,0])),
            (42.51, 74.05, 63.43,       7.778, 11.067, 10.295)),
        (([10,3,0], vectors.angle([1,0,0])), ([0,14,0], vectors.angle([1,-0.5,0])),
            (132.27, 21.16, 26.565,     24.596, 12.0, 14.866)),
        (([5,10,0], vectors.angle([2,-1,0])), ([1,1,0], vectors.angle([1,1,0])),
            (87.4, 21.037, 71.57,       10.370, 3.726, 9.848)),
        
        (([6,1,0], vectors.angle([-1,1,0])), ([15,10,0], vectors.angle([-3,-1,0])),
            (90.0, 26.57, 63.43,        14.230, 6.363, 12.727)),
        (([10,10,0], vectors.angle([-1,-1,0])), ([17,2,0], vectors.angle([-2,0,0])),
            (86.185, 48.814, 45.0,      15.0, 11.313, 10.63)),
        (([20,3,0], vectors.angle([-2,1,0])), ([5,15,0], vectors.angle([-1,-0.5,0])),
            (12.09, 114.78, 53.13,      5.031, 21.801, 19.209)),
        (([12,10,0], vectors.angle([-7,-1,0])), ([3,3,0], vectors.angle([-1,0,0])),
            (29.74, 142.13, 8.13,       40.0, 49.497, 11.401)),
        
        (([5,10,0], vectors.angle([-1,-1,0])), ([10,11,0], vectors.angle([-1.5,-1,0])),
            (146.309, 22.381, 11.309,   14.422, 9.899, 5.099)),
    )
    
    def test_inside_angle(self):
        for act1, act2, expected in self.collision_vals:
            A, B, C, a, b, c = expected
            ansA, ansB, ansC = geometry.inside_angles(act1, act2)
            
            try:
                self.assertAlmostEqual(A, ansA, places=2)
                self.assertAlmostEqual(B, ansB, places=2)
                self.assertAlmostEqual(C, ansC, places=2)
            except Exception as e:
                print("Failure with inputs of A=%s, B=%s" % (act1, act2))
                raise
    
    # This will overlap with the test_inside_angle function but the above
    # will remain incase the functionality is moved around
    def test_collision_angle(self):
        for act1, act2, expected in self.collision_vals:
            A, B, C, a, b, c = expected
            ansA, ansB, ansC, ansa, ansb, ansc = geometry.rect_collision_distance(act1, act2, testing=True)
            
            try:
                self.assertAlmostEqual(A, ansA, places=2)
                self.assertAlmostEqual(B, ansB, places=2)
                self.assertAlmostEqual(C, ansC, places=2)
            except Exception as e:
                print("Failure on angles with inputs of A=%s, B=%s" % (act1, act2))
                raise
            
            try:
                self.assertAlmostEqual(a, ansa, places=2)
                self.assertAlmostEqual(b, ansb, places=2)
                self.assertAlmostEqual(c, ansc, places=2)
            except Exception as e:
                print("Failure on sides with inputs of A=%s, B=%s" % (act1, act2))
                raise