Пример #1
0
def test_does_overlap():
    aabb5 = AABB([(-3, 3), (-3, 3)])
    aabb6 = AABB([(0, 1), (5, 6)])
    aabb7 = AABB([(6.5, 6.5), (5.5, 5.5)])

    for aabb in (aabb5, aabb6, aabb7):
        assert not AABBTree().does_overlap(aabb)

    aabbs = standard_aabbs()
    for indices in itertools.permutations(range(4)):
        tree = AABBTree()
        for i in indices:
            tree.add(aabbs[i])

        assert tree.does_overlap(aabb5)
        assert not tree.does_overlap(aabb6)
        assert not tree.does_overlap(aabb7)
Пример #2
0
def test_does_overlap():
    aabb5 = AABB([(-3, 3), (-3, 3)])
    aabb6 = AABB([(0, 1), (5, 6)])
    aabb7 = AABB([(6.5, 6.5), (5.5, 5.5)])

    not_tree = AABBTree()
    not_tree.add(aabb6)
    not_tree.add(aabb7)

    for aabb in (aabb5, aabb6, aabb7):
        for m in ('DFS', 'BFS'):
            assert not AABBTree().does_overlap(aabb, method=m)

    aabbs = standard_aabbs()
    for indices in itertools.permutations(range(4)):
        tree = AABBTree()
        alt_tree = AABBTree()
        for i_ind, i in enumerate(indices):
            tree.add(aabbs[i])
            alt_tree.add(aabbs[i_ind])

        for m in ('DFS', 'BFS'):
            assert tree.does_overlap(tree, method=m)
            assert alt_tree.does_overlap(tree, method=m)
            assert tree.does_overlap(alt_tree, method=m)

            assert tree.does_overlap(aabb5, method=m)
            assert not tree.does_overlap(aabb6, method=m)
            assert not tree.does_overlap(aabb7, method=m)

            assert not tree.does_overlap(not_tree, method=m)
            assert not not_tree.does_overlap(tree, method=m)
Пример #3
0
class Collision:
    def __init__(self, objects=None):
        self.tree = AABBTree()
        if objects:
            for item in objects:
                if item["type"] == "CUBE":
                    self.add_object(item["pos"],
                                    (item["scale"][0] / 2, item["scale"][1] /
                                     2, item["scale"][2] / 2), item["goal"])
                elif item["type"] == "SPHERE":
                    self.add_object(item["pos"], item["scale"], item["goal"])

    # Returns AABB object with coorect values based on a point and offset
    def get_aabb(self, point, bound):
        return AABB([(point.x - bound[0], point.x + bound[0]),
                     (point.y - bound[1], point.y + bound[1]),
                     (point.z - bound[2], point.z + bound[2])])

    # Add object with position and scale to the tree
    # Sets the position as the value returned in case of collision
    def add_object(self, position, scale, goal):
        self.tree.add(self.get_aabb(position, scale), {
            "pos": position,
            "scale": scale,
            "goal": goal
        })

    # Makes checking for collision on point easier
    def point_collision(self, point, bound):
        return self.tree.does_overlap(self.get_aabb(point, bound))

    # Returns the point object of collided objects
    def collision_objects(self, point, bound):
        return self.tree.overlap_values(self.get_aabb(point, bound))

    # checks if player is between bounds of object on an axis with respect to size
    def is_between(self, player, obj, axis):
        return obj["pos"][axis] - obj["scale"][axis] - player["scale"][
            axis] < player["pos"][axis] < obj["pos"][axis] + obj["scale"][
                axis] + player["scale"][axis]

    # Finds which side of a cube the player is touching
    def get_colliding_face(self, player, obj):
        # Zeroes the axis of the plane on the object the player is touching
        return (1 if self.is_between(player, obj, 0) else 0,
                1 if self.is_between(player, obj, 1) else 0,
                1 if self.is_between(player, obj, 2) else 0)

    # Returns surface vector based on player direction
    def get_surface_vector(self, player, obj):
        directions = self.get_colliding_face(player, obj)
        # Returns a normalized vector that represents the direction of the surface
        # Direction on the non zeroed axes based on player movement
        return Vector(player["direction"].x * directions[0],
                      player["direction"].y * directions[1],
                      player["direction"].z * directions[2]).normalize()

    # Returns slide vector for player on collided object
    def get_slide_vector(self, player, obj):
        surface_vector = self.get_surface_vector(player, obj)
        return surface_vector * player["direction"].dot(surface_vector)

    # Returns motion vector of player
    def move(self, player):
        # collision member set to advoid key error
        player["collision"] = []
        # If no collision return player directly
        if not self.point_collision(player["newpos"], player["scale"]):
            return player
        else:
            # If collision, get slide vector for each object collided with
            for item in self.collision_objects(player["newpos"],
                                               player["scale"]):
                player["direction"] = self.get_slide_vector(player, item)
                player["collision"].append(
                    self.get_colliding_face(player, item))
                if item["goal"]:
                    player["collision"].append((0, 0, 0))
            return player