Example #1
0
 def get_colliders(self, bounding_shape, position, ignored=[], typefilter=None):
     """
     Returns a list of game objects in the world that are currently
     colliding with the given bounding_shape at the given position. This
     method performs no collision resolution.
     
     This method is useful for collision between game objects in the world
     and some bounding shape that may not be "in" the world (e.g., a
     temporary bounding shape used for abilities).
     
     Arguments:
     bounding_shape -- The shape to check objects against.
     position -- The position of the shape to check objects against.
     ignored -- A list of game objects to ignore collision with.
     typefilter -- A class type that the colliding object must an instance
         (or derived instance) of.
     """
     colliders = []
     for object in self.objects:
         if object.bounding_shape is None:
             # Can't collide with an object that has no bounding shape.
             continue
         if typefilter is not None and not isinstance(object, typefilter):
             # Only collide with filtered objects.
             continue
         
         result = CollisionDetector.check_collision(bounding_shape, position, object.bounding_shape, object.position)
         if result is not False and object not in ignored:
             colliders.append(object)
             
     return colliders
Example #2
0
    def run(self):
        AbilityInstance.run(self)
        if self.player.world.is_master:
            # create the bounding circle to check collision against
            bounding_cone = collision.BoundingCone(self.hit_radius,
                                                   self.player.rotation,
                                                   self.hit_angle)

            # get a list of colliding players
            self.targets = self.player.world.get_colliders(
                bounding_cone, self.player.position, [self.player],
                objects.Player)

            # for each player, apply effects
            for player in self.targets:
                # get force vector for other player
                force_vector = ((player.position[0] - self.player.position[0],
                                 player.position[1] - self.player.position[1]))
                force_vector = CollisionDetector.normalise_vector(force_vector)
                player.force_vector = (force_vector[0] *
                                       self.starting_strength,
                                       force_vector[1] *
                                       self.starting_strength)
                print "Gust of wind collided with another player!"

        # end the effect
        self.expire()
Example #3
0
 def apply_force(self,
                 vector,
                 strength,
                 acceleration_factor=1,
                 duration=False):
     self.force_vector = CollisionDetector.normalise_vector(vector)
     self.force_strength = strength
     self.force_duration = duration
     self.force_acceleration = acceleration_factor
     self.force_applied = True
Example #4
0
 def update(self, dt):
     AbilityInstance.update(self, dt)
     if self.player.world.is_master:
         if self.player_hooked is None:
             return
         if collision.CollisionDetector.check_collision(collision.BoundingCircle(8), 
                                                        self.player_hooked.position,
                                                        self.player.bounding_shape, 
                                                        self.player.position):
             self.player_hooked.is_hooked = False
             self.player_hooked.force_vector = (0, 0)
             self.expire()
         else:
             fv = (self.player.position[0] - self.player_hooked.position[0],
                   self.player.position[1] - self.player_hooked.position[1])
             fv = CollisionDetector.normalise_vector(fv)
             fv = (fv[0] * self.retraction_speed, fv[1] * self.retraction_speed)
             self.player_hooked.force_vector = fv
Example #5
0
 def run(self):
     AbilityInstance.run(self)
     if self.player.world.is_master:
         # create the bounding circle to check collision against
         bounding_cone = collision.BoundingCone(self.hit_radius, self.player.rotation, self.hit_angle) 
         
         # get a list of colliding players
         self.targets = self.player.world.get_colliders(bounding_cone, self.player.position,
                                                     [self.player], objects.Player)
         
         # for each player, apply effects
         for player in self.targets:
             # get force vector for other player
             force_vector = ((player.position[0] - self.player.position[0],
                              player.position[1] - self.player.position[1]))
             force_vector = CollisionDetector.normalise_vector(force_vector)
             player.force_vector = (force_vector[0] * self.starting_strength,
                 force_vector[1] * self.starting_strength)
             # print "Gust of wind collided with another player!"
             
     # end the effect
     self.expire()
Example #6
0
    def _move(self, move_vector, already_collided=None):
        """
        Moves the object by the given movement vector (relative to the current
        position and performs collision detection and resolution.
        
        Arguments:
        move_vector -- The vector containing the x and z components to move the
            object in (relative to the current position).
        already_collided -- A set of objects previously collided with in this
            gamestate update that need to persist through _move() calls.
        """
        
        # If the movement vector is 0, we don't have to do anything.
        if move_vector == (0, 0):
            return

        # Calculate the new position we want to move to.
        new_pos = (self._position[0] + move_vector[0],
                   self._position[1] + move_vector[1])
        
        # If the object doesn't have a bounding shape then we don't need to
        # worry about collision detection & resolution and can simply update
        # the position and return.
        if self.bounding_shape is None:
            self.position = new_pos
            return
        
        # Otherwise we need to do collision detection.
        
        # @todo: possible optimizations:
        #   - Check un-passable objects first so we can restart _move sooner (if needed).
        #   - Check only against nearby objects (quadtree?)
        
        # Initialize the set of objects we collide with in this object's
        # update (for later use in collision resolution).
        if already_collided is None:
            # If already_collided (a function argument) was not pased then no
            # objects have already collided with this object during this
            # object's update, so initialize it to an empty set.
            collided_objects = set()
        else:
            # Otherwise we already have some objects we have collided with (but
            # not performed resolution on), so initialize our set to those
            # previously collided with objects.
            collided_objects = already_collided
        
        # Loop over all objects in the world to test against.
        for object in self.world.objects:
            if self == object:
                # Can't collide with ourself.
                continue
                
            if object.bounding_shape is None:
                # Can't collide with an object that has no bounding shape.
                continue

            # Cast a ray from where we are to where we are moving to and check
            # if this ray collides with the object. This is to look for any
            # objects that may be between our old position and our new
            # position. This result will be True if the ray collides with the
            # object and False if not.
            rayResult = CollisionDetector.is_between(object.bounding_shape, object.position, self.position, new_pos)
            
            # Check if our bounding shape at our new position would overlap
            # with the object's bounding shape. The result will be None if
            # there is no overlap, or if there is a collision it will be the
            # position we should reset to if the object is not passable as a
            # part of collision resolution.
            shapeResult = CollisionDetector.check_collision_and_resolve(self.bounding_shape, new_pos, self.position, 
                                                                        object.bounding_shape, object.position)
            
            if rayResult is not False and shapeResult is False:
                # The object collided with our ray, but not with our shape,
                # so we must have jumped over it.
                
                # If the object is not passable, then this is a critical error
                # and we will completely deny the move by returning.
                if not object.isPassable:
                    return
                    
                # Otherwise add the object to our set of collided objects.
                collided_objects.add(object)
                
            if shapeResult is not False:
                # Our new bounding shape will be overlapping with another
                # object's bounding shape.
                
                # Add the object to our set of collided objects.
                collided_objects.add(object)
                
                # If the object is not passable, then we need to move to the
                # new position that is provided by the result and redo the
                # collision detection based on that new position. Call
                # self._move() to do this and then return.
                
                if not object.isPassable:
                    # We will use the shapeResult value (a corrected movement
                    # vector) returned from check_collision to move ourself
                    # flush against the object we collided with.
                    move_mm = (move_vector[0] + shapeResult[0],move_vector[1] + shapeResult[1])
                    self._move((move_vector[0] + shapeResult[0],
                                move_vector[1] + shapeResult[1]),
                               set([object]))
                    return

        # Now that collision detection is complete, update our position to the
        # previously calculated new position.
        self.position = new_pos
        
        # We now have a set of objects that we have collided with. Call
        # .collide() on each of those objects to perform collision resolution.
        for object in collided_objects:
            object.collide(self)
Example #7
0
 def apply_force(self, vector, strength, acceleration_factor=1, duration=False):
     self.force_vector = CollisionDetector.normalise_vector(vector)
     self.force_strength = strength
     self.force_duration = duration
     self.force_acceleration = acceleration_factor
     self.force_applied = True