Beispiel #1
0
 def __init__(self, floor_data, parent_game):
     self._scenario_ = TileMapLayer(floor_data, mask=get_color_mask())
     self._camera_ = Camera(self._scenario_)
     self._game_ = parent_game
     self._game_objects_ = {}
     self._decorations_ = {}
     self.block = self._compute_walls_collisions_()
     self._spawns_ = self._get_spawns_()
Beispiel #2
0
class Room:
    '''Container for all in-game elements'''
    def __init__(self, floor_data, parent_game):
        self._scenario_ = TileMapLayer(floor_data, mask=get_color_mask())
        self._camera_ = Camera(self._scenario_)
        self._game_ = parent_game
        self._game_objects_ = {}
        self._decorations_ = {}
        self.block = self._compute_walls_collisions_()
        self._spawns_ = self._get_spawns_()

    @property
    def initial_objects(self):
        '''List of all objects defined in the map initially'''
        return self._scenario_.objects

    @property
    def game_objects(self):
        '''Map of current-living objects'''
        return self._game_objects_

    def _compute_walls_collisions_(self):
        block = []
        for y in range(self._scenario_.map_height):
            row = []
            for x in range(self._scenario_.map_width):
                row.append(self._scenario_.get_cell_at(x, y) in BLOCK_CELLS)
            block.append(row)
        return block

    def _get_spawns_(self):
        spawns = {}
        for candidate in self._game_objects_.values():
            if isinstance(candidate, Spawn):
                spawns[candidate.spawn] = candidate.position
        return spawns

    @property
    def camera(self):
        '''Room camera'''
        return self._camera_

    def set_camera_target(self, game_object):
        '''Change target of the camera'''
        self._camera_.set_target(game_object)

    @property
    def tilemaps(self):
        '''Map layers'''
        return self._scenario_

    def spawn(self, game_object):
        '''Spawn new object at a spawn zone'''
        spawn_zone = game_object.spawn if game_object.spawn in self._spawns_ else DEFAULT_SPAWN
        self.spawn_at(game_object, self._spawns_[spawn_zone])

    def spawn_at(self, game_object, position):
        '''Spawn new object at a given position'''
        self._game_objects_[game_object.identifier] = game_object
        self._game_objects_[game_object.identifier].position = position
        self._game_objects_[game_object.identifier].room = self
        self._spawns_.update(self._get_spawns_())

    def spawn_decoration(self, decoration_id, position):
        '''Spawn decoration'''
        decoration = game.decoration.new(decoration_id, position)
        self._decorations_[decoration.identifier] = decoration
        self._decorations_[decoration.identifier].room = self

    def kill(self, game_object):
        '''Kill an object'''
        identifier = game_object if isinstance(game_object,
                                               str) else game_object.identifier

        if identifier == self._game_.identifier:
            self._game_.player.attribute.update(
                self._game_objects_[identifier].attribute)

        if identifier in self._game_objects_:
            self._game_objects_[identifier].room = None
            del self._game_objects_[identifier]
        elif identifier in self._decorations_:
            self._decorations_[identifier].room = None
            del self._decorations_[identifier]

        if identifier == self._game_.identifier:
            self._game_.end_current_room()

    def open_door(self, door_identifier):
        '''Open a existing door'''
        door_position = self._search_door_(door_identifier)
        if not door_position:
            return
        doors = self._adjacent_doors_(door_position)
        for door in doors:
            self.kill(door)
            self.send_event(('kill_object', door))

    def _search_door_(self, door_identifier):
        if door_identifier not in self._game_objects_:
            return None
        y = 0
        for row in self.block:
            x = 0
            for cell in row:
                if cell == door_identifier:
                    return (x, y)
                x += 1
            y += 1
        return None

    def _adjacent_doors_(self, location, visited=None):
        if not visited:
            visited = []
        x, y = location
        if location in visited:
            return []
        visited.append((x, y))
        if (y not in range(len(self.block))) or (x not in range(
                len(self.block[0]))):
            return []
        identifier = self.block[y][x]
        door = self._game_objects_[identifier]
        if not isinstance(door, Door):
            return []
        doors = [door.identifier]
        door_tile_id = door.attribute[TILE_ID]
        for dir_x, dir_y in _DOOR_DIRECTION_[door_tile_id]:
            doors += self._adjacent_doors_((x + dir_x, y + dir_y), visited)
        return doors

    def update(self):
        '''A game loop iteration'''
        for game_object in list(self._game_objects_.values()):
            game_object.update()
            if not game_object.acting:
                self.kill(game_object)
            if game_object.body:
                self.check_collisions_with(game_object)

    def render(self):
        '''Draw a frame'''
        self._camera_.update()
        self._scenario_.render(*self._camera_.position)

        for game_object in self._game_objects_.values():
            game_object.render(*self._camera_.position)

        for decoration in list(self._decorations_.values()):
            decoration.render(*self._camera_.position)

    def check_collisions_with(self, game_object):
        '''Compute collisions for all game objects'''
        if not game_object.body:
            return
        for other_game_object in list(self._game_objects_.values()):
            if (other_game_object is
                    game_object) or (not other_game_object.body):
                continue
            if game_object.body.collides_with(other_game_object):
                self.send_event(('collision', game_object.identifier,
                                 other_game_object.identifier))

    def send_event(self, event):
        '''Send event to orchestrator'''
        self._game_.send_event(event)