Ejemplo n.º 1
0
 def __init__(self, *args):
     _range_of_action, x, y = args
     super(ProximityObject, self).__init__(x, y)
     self.pos_row, self.pos_col = utils.norm_to_cell(x), utils.norm_to_cell(y)
     self.geometric_point = Point(x, y) # This will be used to compute intersections with the players' vision polygon
     self.range_of_action = _range_of_action
     self.weapon = None # has to be overwritten by children
Ejemplo n.º 2
0
    def __move_player(self, player, dx, dy):
        """

        Moves the given player using the given dx nd dy deltas for x and y axis
        taking into account collisions with obstacles

        :param player: Instance of Player class, the player we want to move
        :param dx: float, the x coordinate difference we want to apply to the current player
            (may or may not be pplied depending on wether there are collisions)
        :param dy: float, the y coordinate difference we want to apply to the current player
            (may or may not be pplied depending on wether there are collisions)
        :return None
        """

        x_to_be, y_to_be = player.posx + dx, player.posy + dy

        # Do not go out of the map please :

        if x_to_be > self.slmap.max_x:
            x_to_be = self.slmap.max_x

        if y_to_be > self.slmap.max_y:
            y_to_be = self.slmap.max_y

        if x_to_be < 0:
            x_to_be = 0

        if y_to_be < 0:
            y_to_be = 0

        row, col = utils.norm_to_cell(player.posy), utils.norm_to_cell(player.posx)
        row_to_be, col_to_be = utils.norm_to_cell(y_to_be), utils.norm_to_cell(x_to_be)

        is_obs_by_dx = self.slmap.is_obstacle_from_cell_coords(row, col_to_be)
        is_obs_by_dy = self.slmap.is_obstacle_from_cell_coords(row_to_be, col)
        if is_obs_by_dx is False and is_obs_by_dy is False: # no collision
            player.posx = x_to_be
            player.posy = y_to_be
        elif is_obs_by_dx is False: # no collision only for x displacement
            player.posx = x_to_be
            player.posy = row_to_be * const.CELL_SIZE - 1 # maximum possible posy before colliding
        elif is_obs_by_dy is False: # no collision only for y displacement
            player.posy = y_to_be
            player.posx = col_to_be * const.CELL_SIZE - 1 # maximum possible posx before colliding
        else: # collision along all axis
            player.posx = col_to_be * const.CELL_SIZE - 1 # maximum possible posx before colliding
            player.posy = row_to_be * const.CELL_SIZE - 1 # maximum possible posy before colliding

        player.compute_hitbox()

        return player # allow chaining
Ejemplo n.º 3
0
    def __for_obstacle_in_range(self, vector, callback, **callback_args):
        """
            Finds the obstacle in the given range (range = a distance range + an angle (factorized in the "vector" argument))
            and executes the callback for each found obstacle

            :param vector: range/direction vector, of the form ((x_orig, y_orig), (x_end, y_end)) in real map coordinates
            :param callback: callback function, signature must be func([self, ]vector, row, col, **kwargs)
            :param callback_args: Additional arguments that will be passed to the callback function when executed

            /!\ Important /!\ Returns:
                - None either if the callback was never called or if it never returned anything else than None
                - the callback value, if a callback call returns anything that is not None
        """
        col_orig = utils.norm_to_cell(vector[0][0]) # x origin, discretize to respect map's tiles (as, we will needs the true coordinates of the obstacle, when we'll find one)
        _logger.info("__shoot_collide_with_obstacle(): x=" + str(col_orig))
        row = utils.norm_to_cell(vector[0][1]) # y origin, same process as for x
        _logger.info("__shoot_collide_with_obstacle(): y=" + str(row))
        col_end = int(utils.norm_to_cell(vector[1][0]))
        row_end = int(utils.norm_to_cell(vector[1][1]))
        # The following variables will be used to increment in the "right direction" (negative if the end if lower
        # than the origin, etc....
        col_increment_sign = 1 if (col_end-col_orig) > 0 else -1
        row_increment_sign = 1 if (row_end-row) > 0 else -1
        # A bit of explanation of the conditions here :
        # row < self.slmap.height --> Self explanatory, do not go over the map (as the line is multiplied by a
        # coefficient, this check is necessary
        # (row-row_end) != row_increment_sign --> This means that we want to stop when the "row" variable has gone one
        # unit further than the row_end variable. row_increment_sign will always have the same sign as
        # (row-row_end) when row is one unit further than row_end (by further we mean : one iteration further, in the
        # "direction" in which we are iterating: that could be forward or backward). Stopping when we are "one further"
        # means that we iterate until we reach the row_end... INCLUDED! (else, would not work when perfectly aligned)
        # same thing for the condition with "row" replaced by "col"
        while row < self.slmap.height and (row-row_end) != row_increment_sign:
            col = col_orig
            while col < self.slmap.width and (col-col_end) != col_increment_sign:
                if self.slmap.is_obstacle_from_cell_coords(row, col):
                    callback_result = callback(vector, row, col, **callback_args)
                    if callback_result is not None:
                        return callback_result
                col += col_increment_sign * 1
            row += row_increment_sign * 1
        return None
Ejemplo n.º 4
0
    def step(self):
        # TODO: Maybe re-write the following lines, for a better handling of
        #       game termination.
        if self.auto_mode and self.__game_finished():
            self.end_of_game()
            return

        # Update players' positions and visions
        for p in self.__players:
            normalized_array = self.__get_normalized_direction_vector_from_angle(p.move_angle)
            self.__move_player(p, normalized_array[0] * p.speedx, normalized_array[1] * p.speedy)
            p.obstacles_in_sight = []
            p.obstacles_in_sight_n = 0
            # ------- Update player's sight -------
            # Parametrize things for occlusion (get obstacles that need to be taken into account by occlusion)
            sight_direction = self.__get_normalized_direction_vector_from_angle(p.sight_angle) * p.sight_range
            # A bit bruteforce here, let's use a circle instead of the real shaped vision
            # Just because there won't be many items to go through anyway
            # and for simplicity's and implementation speed's sakes
            y_start = max(0, p.posy - p.sight_range)
            y_end = min(self.slmap.max_y, p.posy + p.sight_range)
            x_start = max(0, p.posx - p.sight_range)
            x_end = min(self.slmap.max_x, p.posx + p.sight_range)
            row_start   = utils.norm_to_cell(y_start)
            row_end     = utils.norm_to_cell(y_end)
            col_start   = utils.norm_to_cell(x_start)
            col_end     = utils.norm_to_cell(x_end)
            vect = ((x_start, y_start), (x_end, y_end))
            self.__for_obstacle_in_range(vect, self.__occlusion_get_obstacle_in_range_callback, player=p)
            p.compute_sight_polygon_coords()
            # Launch occlusion
            p.sight_vertices, p.occlusion_polygon = occlusion(p.posx, p.posy, p.sight_polygon_coords, p.obstacles_in_sight, p.obstacles_in_sight_n)

            # ---------- Update player's visible objects list ----------
            # Note: Here we only go through the visible objects that are in a given range, not through all of them
            # We will go through the complete list, in order to update them, later in this method
            del p.visible_objects[:] # Empty the list

            for row in xrange(row_start, row_end+1):
                for col in xrange(col_start, col_end+1):
                    try:
                        for item in self.__actionable_items[self.__map_item_key_from_row_col(row, col)]:
                            if p.occlusion_polygon.intersects(item.geometric_point):
                                p.add_new_visible_object(item)
                    except KeyError:
                        pass # There was nothing at this (row,col) position...
                    try:
                        for item in self.__proximity_objects[self.__map_item_key_from_row_col(row, col)]:
                            if p.occlusion_polygon.intersects(item.geometric_point):
                                p.add_new_visible_object(item)
                    except KeyError:
                        pass # There was nothing at this (row,col) position...

            # ---------- Update player's visible players list ----------

            del p.visible_players[:] # Empty the list
            # Re-populate it
            for p2 in self.__players:
                if p2 is p:
                    continue # Do not include ourself in visible objects
                if p.occlusion_polygon.intersects(p2.hitbox):
                    p.visible_players.append((p2.player_id, p2.posx, p2.posy, p2.move_angle))
        # end of by player loop

        # Now go through all of the visible items to update them
        for row in xrange(0, self.slmap.height):
            for col in xrange(0, self.slmap.width):
                try:
                    for item in self.__actionable_items[self.__map_item_key_from_row_col(row, col)]:
                        item.update()
                except KeyError:
                    pass # There was nothing at this (row,col) position...
                try:
                    for item in self.__proximity_objects[self.__map_item_key_from_row_col(row, col)]:
                        item.update()
                        # Try to activate the proximity object on this player
                        for p_ in self.__players:
                            item.activate(p_)
                except KeyError:
                    pass # There was nothing at this (row,col) position...
Ejemplo n.º 5
0
 def __init__(self, *args):
     x, y = args
     super(ActionableItem, self).__init__(x, y)
     self.pos_row, self.pos_col = utils.norm_to_cell(x), utils.norm_to_cell(y)
     self.geometric_point = Point(x, y) # This will be used to compute intersections with the players' vision polygon