예제 #1
0
    def __init__(self, game, size_x, size_y):
        self.game = game
        self.actor_system = ActorSystem(self)
        self.position_system = PositionSystem()
        self.render_system = RenderSystem(self)
        self.size_x = size_x
        self.size_y = size_y

        self._entities = set()

        self._generate_level()

        self.render_system.render_level()
        self.render_system.update_player()
        self.player.get(FOV).update_light()
예제 #2
0
파일: level.py 프로젝트: nadako/dungeons
    def __init__(self, game, size_x, size_y):
        self.game = game
        self.actor_system = ActorSystem(self)
        self.position_system = PositionSystem()
        self.render_system = RenderSystem(self)
        self.size_x = size_x
        self.size_y = size_y

        self._entities = set()

        self._generate_level()

        self.render_system.render_level()
        self.render_system.update_player()
        self.player.get(FOV).update_light()
예제 #3
0
class Level(object):
    def __init__(self, game, size_x, size_y):
        self.game = game
        self.actor_system = ActorSystem(self)
        self.position_system = PositionSystem()
        self.render_system = RenderSystem(self)
        self.size_x = size_x
        self.size_y = size_y

        self._entities = set()

        self._generate_level()

        self.render_system.render_level()
        self.render_system.update_player()
        self.player.get(FOV).update_light()

    def _generate_level(self):
        self._layout = LayoutGenerator(self.size_x, self.size_y, max_rooms=30)
        self._layout.generate()
        self._process_layout()
        self._add_features()
        self._add_monsters()
        self._add_items()
        self._add_player()

    def _process_layout(self):
        grid = self._layout.grid
        for x in xrange(grid.size_x):
            for y in xrange(grid.size_y):
                tile = grid[x, y]
                if tile in (LayoutGenerator.TILE_DOOR_CLOSED,
                            LayoutGenerator.TILE_DOOR_OPEN):
                    self.add_entity(
                        create_door(x, y,
                                    tile == LayoutGenerator.TILE_DOOR_OPEN))
                    self.add_entity(
                        Entity(Description('Floor'), LayoutRenderable(tile),
                               Position(x, y)))
                elif tile == LayoutGenerator.TILE_WALL:
                    self.add_entity(
                        Entity(Description('Wall'), Blocker(True, True),
                               LayoutRenderable(tile),
                               Position(x, y, Position.ORDER_WALLS)))
                elif tile == LayoutGenerator.TILE_FLOOR:
                    self.add_entity(
                        Entity(Description('Floor'), LayoutRenderable(tile),
                               Position(x, y)))

    def _add_features(self):
        # TODO: factor this out into feature generator
        for room in self._layout.rooms:
            feature = random.choice([None, 'light', 'fountain', 'library'])
            if feature == 'light':
                coords = random.sample([
                    (room.x + 1, room.y + 1),
                    (room.x + room.grid.size_x - 2, room.y + 1),
                    (room.x + 1, room.y + room.grid.size_y - 2),
                    (room.x + room.grid.size_x - 2,
                     room.y + room.grid.size_y - 2),
                ], random.randint(1, 4))
                for x, y in coords:
                    self.add_entity(
                        Entity(Renderable(light_anim, memorable=True),
                               Blocker(blocks_movement=True),
                               Description('Light'),
                               Position(x, y, Position.ORDER_FEATURES)))
            elif feature == 'fountain':
                self.add_entity(
                    Entity(
                        Renderable(fountain_anim, memorable=True),
                        Blocker(blocks_movement=True), Description('Fountain'),
                        Position(room.x + room.grid.size_x / 2,
                                 room.y + room.grid.size_y / 2,
                                 Position.ORDER_FEATURES)))
            elif feature == 'library':
                y = room.y + room.grid.size_y - 1
                for x in xrange(room.x + 1, room.x + room.grid.size_x - 1):
                    if self._layout.grid[x, y] != LayoutGenerator.TILE_WALL:
                        continue
                    if x == room.x + 1 and self._layout.grid[
                            room.x, y - 1] != LayoutGenerator.TILE_WALL:
                        continue
                    if x == room.x + room.grid.size_x - 2 and self._layout.grid[
                            x + 1, y - 1] != LayoutGenerator.TILE_WALL:
                        continue
                    self.add_entity(
                        Entity(
                            Renderable(random.choice(library_texes),
                                       memorable=True),
                            Blocker(blocks_movement=True),
                            Description('Bookshelf'),
                            Position(x, y - 1, Position.ORDER_FEATURES)))

    def _add_monsters(self):
        for room in self._layout.rooms:
            for i in xrange(random.randint(0, 3)):
                x = random.randrange(room.x + 1, room.x + room.grid.size_x - 1)
                y = random.randrange(room.y + 1, room.y + room.grid.size_y - 1)
                if not self.get_movement_blocker(x, y):
                    self.add_entity(create_random_monster(x, y))

    def _add_items(self):
        for room in self._layout.rooms:
            if random.random() > 0.3:
                continue
            x = random.randrange(room.x + 1, room.x + room.grid.size_x - 1)
            y = random.randrange(room.y + 1, room.y + room.grid.size_y - 1)
            if not self.get_movement_blocker(x, y):
                self.add_entity(
                    Entity(
                        Description('Gold'),
                        Renderable(random.choice(gold_texes)),
                        Position(x, y, order=Position.ORDER_ITEMS),
                        Item('gold', quantity=random.randint(1, 50)),
                    ))

    def _add_player(self):
        room = random.choice(
            self._layout.rooms)  # TODO: refactor this to stairs up/down
        self.player = create_player(room.x + room.grid.size_x / 2,
                                    room.y + room.grid.size_y / 2)
        self.player.add(MessageLogger(self.game.message_log))
        self.player.listen('fov_updated', self._on_player_fov_update)
        self.add_entity(self.player)

    def _on_player_fov_update(self, player, old_lightmap, new_lightmap):
        self.render_system.update_light(old_lightmap, new_lightmap)

    def get_sight_blocker(self, x, y):
        if not self._layout.in_bounds(x, y):
            return BOUNDS

        for entity in self.position_system.get_entities_at(x, y):
            blocker = entity.get(Blocker)
            if blocker and blocker.blocks_sight:
                return blocker

        return None

    def get_movement_blocker(self, x, y):
        if not self._layout.in_bounds(x, y):
            return BOUNDS

        for entity in self.position_system.get_entities_at(x, y):
            blocker = entity.get(Blocker)
            if blocker and blocker.blocks_movement:
                return blocker

        return None

    def add_entity(self, entity):
        entity.level = self
        self._entities.add(entity)

        if entity.has(Position):
            self.position_system.add_entity(entity)

            if entity.has(Health):
                entity.listen('take_damage', self._on_take_damage)

            if entity.has(Blocker):
                entity.listen('blocks_sight_change',
                              self._on_blocks_sight_change)

            if entity.has(Renderable):
                self.render_system.add_entity(entity)

        if entity.has(Actor):
            self.actor_system.add_entity(entity)

    def remove_entity(self, entity):
        self._entities.remove(entity)
        entity.level = None

        if entity.has(Position):
            self.position_system.remove_entity(entity)

            if entity.has(Health):
                entity.unlisten('take_damage', self._on_take_damage)

            if entity.has(Blocker):
                entity.unlisten('blocks_sight_change',
                                self._on_blocks_sight_change)

            if entity.has(Renderable):
                self.render_system.remove_entity(entity)

        if entity.has(Actor):
            self.actor_system.remove_entity(entity)

    def _on_take_damage(self, entity, amount, source):
        pos = entity.get(Position)
        self.render_system.animate_damage(pos.x, pos.y, amount)

    def _on_blocks_sight_change(self, entity):
        pos = entity.get(Position)
        fov = self.player.get(FOV)
        if fov.is_in_fov(pos.x, pos.y):
            fov.update_light()

    def tick(self):
        self.actor_system.update()

    def get_wall_transition(self, x, y):
        return self._layout.get_wall_transition(x, y)
예제 #4
0
파일: level.py 프로젝트: nadako/dungeons
class Level(object):

    def __init__(self, game, size_x, size_y):
        self.game = game
        self.actor_system = ActorSystem(self)
        self.position_system = PositionSystem()
        self.render_system = RenderSystem(self)
        self.size_x = size_x
        self.size_y = size_y

        self._entities = set()

        self._generate_level()

        self.render_system.render_level()
        self.render_system.update_player()
        self.player.get(FOV).update_light()

    def _generate_level(self):
        self._layout = LayoutGenerator(self.size_x, self.size_y, max_rooms=30)
        self._layout.generate()
        self._process_layout()
        self._add_features()
        self._add_monsters()
        self._add_items()
        self._add_player()

    def _process_layout(self):
        grid = self._layout.grid
        for x in xrange(grid.size_x):
            for y in xrange(grid.size_y):
                tile = grid[x, y]
                if tile in (LayoutGenerator.TILE_DOOR_CLOSED, LayoutGenerator.TILE_DOOR_OPEN):
                    self.add_entity(create_door(x, y, tile == LayoutGenerator.TILE_DOOR_OPEN))
                    self.add_entity(Entity(Description('Floor'), LayoutRenderable(tile), Position(x, y)))
                elif tile == LayoutGenerator.TILE_WALL:
                    self.add_entity(Entity(Description('Wall'), Blocker(True, True), LayoutRenderable(tile), Position(x, y, Position.ORDER_WALLS)))
                elif tile == LayoutGenerator.TILE_FLOOR:
                    self.add_entity(Entity(Description('Floor'), LayoutRenderable(tile), Position(x, y)))

    def _add_features(self):
        # TODO: factor this out into feature generator
        for room in self._layout.rooms:
            feature = random.choice([None, 'light', 'fountain', 'library'])
            if feature == 'light':
                coords = random.sample([
                    (room.x + 1, room.y + 1),
                    (room.x + room.grid.size_x - 2, room.y + 1),
                    (room.x + 1, room.y + room.grid.size_y - 2),
                    (room.x + room.grid.size_x - 2, room.y + room.grid.size_y - 2),
                ], random.randint(1, 4))
                for x, y in coords:
                    self.add_entity(Entity(
                        Renderable(light_anim, memorable=True),
                        Blocker(blocks_movement=True),
                        Description('Light'),
                        Position(x, y, Position.ORDER_FEATURES)
                    ))
            elif feature == 'fountain':
                self.add_entity(Entity(
                    Renderable(fountain_anim, memorable=True),
                    Blocker(blocks_movement=True),
                    Description('Fountain'),
                    Position(room.x + room.grid.size_x / 2, room.y + room.grid.size_y / 2, Position.ORDER_FEATURES)
                ))
            elif feature == 'library':
                y = room.y + room.grid.size_y - 1
                for x in xrange(room.x + 1, room.x + room.grid.size_x - 1):
                    if self._layout.grid[x, y] != LayoutGenerator.TILE_WALL:
                        continue
                    if x == room.x + 1 and self._layout.grid[room.x, y - 1] != LayoutGenerator.TILE_WALL:
                        continue
                    if x == room.x + room.grid.size_x - 2 and self._layout.grid[x + 1, y - 1] != LayoutGenerator.TILE_WALL:
                        continue
                    self.add_entity(Entity(
                        Renderable(random.choice(library_texes), memorable=True),
                        Blocker(blocks_movement=True),
                        Description('Bookshelf'),
                        Position(x, y - 1, Position.ORDER_FEATURES)
                    ))

    def _add_monsters(self):
        for room in self._layout.rooms:
            for i in xrange(random.randint(0, 3)):
                x = random.randrange(room.x + 1, room.x + room.grid.size_x - 1)
                y = random.randrange(room.y + 1, room.y + room.grid.size_y - 1)
                if not self.get_movement_blocker(x, y):
                    self.add_entity(create_random_monster(x, y))

    def _add_items(self):
        for room in self._layout.rooms:
            if random.random() > 0.3:
                continue
            x = random.randrange(room.x + 1, room.x + room.grid.size_x - 1)
            y = random.randrange(room.y + 1, room.y + room.grid.size_y - 1)
            if not self.get_movement_blocker(x, y):
                self.add_entity(Entity(
                    Description('Gold'),
                    Renderable(random.choice(gold_texes)),
                    Position(x, y, order=Position.ORDER_ITEMS),
                    Item('gold', quantity=random.randint(1, 50)),
                ))

    def _add_player(self):
        room = random.choice(self._layout.rooms) # TODO: refactor this to stairs up/down
        self.player = create_player(room.x + room.grid.size_x / 2, room.y + room.grid.size_y / 2)
        self.player.add(MessageLogger(self.game.message_log))
        self.player.listen('fov_updated', self._on_player_fov_update)
        self.add_entity(self.player)

    def _on_player_fov_update(self, player, old_lightmap, new_lightmap):
        self.render_system.update_light(old_lightmap, new_lightmap)

    def get_sight_blocker(self, x, y):
        if not self._layout.in_bounds(x, y):
            return BOUNDS

        for entity in self.position_system.get_entities_at(x, y):
            blocker = entity.get(Blocker)
            if blocker and blocker.blocks_sight:
                return blocker

        return None

    def get_movement_blocker(self, x, y):
        if not self._layout.in_bounds(x, y):
            return BOUNDS

        for entity in self.position_system.get_entities_at(x, y):
            blocker = entity.get(Blocker)
            if blocker and blocker.blocks_movement:
                return blocker

        return None

    def add_entity(self, entity):
        entity.level = self
        self._entities.add(entity)

        if entity.has(Position):
            self.position_system.add_entity(entity)

            if entity.has(Health):
                entity.listen('take_damage', self._on_take_damage)

            if entity.has(Blocker):
                entity.listen('blocks_sight_change', self._on_blocks_sight_change)

            if entity.has(Renderable):
                self.render_system.add_entity(entity)

        if entity.has(Actor):
            self.actor_system.add_entity(entity)


    def remove_entity(self, entity):
        self._entities.remove(entity)
        entity.level = None

        if entity.has(Position):
            self.position_system.remove_entity(entity)

            if entity.has(Health):
                entity.unlisten('take_damage', self._on_take_damage)

            if entity.has(Blocker):
                entity.unlisten('blocks_sight_change', self._on_blocks_sight_change)

            if entity.has(Renderable):
                self.render_system.remove_entity(entity)

        if entity.has(Actor):
            self.actor_system.remove_entity(entity)


    def _on_take_damage(self, entity, amount, source):
        pos = entity.get(Position)
        self.render_system.animate_damage(pos.x, pos.y, amount)

    def _on_blocks_sight_change(self, entity):
        pos = entity.get(Position)
        fov = self.player.get(FOV)
        if fov.is_in_fov(pos.x, pos.y):
            fov.update_light()

    def tick(self):
        self.actor_system.update()

    def get_wall_transition(self, x, y):
        return self._layout.get_wall_transition(x, y)