示例#1
0
    def render_level(self):
        vertices = []
        tex_coords = []

        for x in xrange(self._level.size_x):
            for y in xrange(self._level.size_y):
                x1 = x * 8
                x2 = x1 + 8
                y1 = y * 8
                y2 = y1 + 8

                for entity in self._level.position_system.get_entities_at(
                        x, y):
                    renderable = entity.get(LayoutRenderable)
                    if renderable:
                        tile = renderable.tile
                        break
                else:
                    continue

                # always add floor, because we wanna draw walls above floor
                vertices.extend((x1, y1, x2, y1, x2, y2, x1, y2))
                tex_coords.extend(floor_tex.tex_coords)

                if tile == LayoutGenerator.TILE_WALL:
                    # if we got wall, draw it above floor
                    tex = get_wall_tex(self._level.get_wall_transition(x, y))
                    vertices.extend((x1, y1, x2, y1, x2, y2, x1, y2))
                    tex_coords.extend(tex.tex_coords)

        group = TextureGroup(
            dungeon_tex,
            pyglet.graphics.OrderedGroup(Position.ORDER_FLOOR,
                                         self._level_group))
        self._level_vlist = self._batch.add(
            len(vertices) / 2,
            pyglet.gl.GL_QUADS,
            group,
            ('v2i/static', vertices),
            ('t3f/statc', tex_coords),
        )

        group = pyglet.graphics.OrderedGroup(Position.ORDER_PLAYER + 1,
                                             self._level_group)
        self._light_overlay = LightOverlay(self._level.size_x,
                                           self._level.size_y, self._batch,
                                           group)
示例#2
0
文件: render.py 项目: nadako/dungeons
    def render_level(self):
        vertices = []
        tex_coords = []

        for x in xrange(self._level.size_x):
            for y in xrange(self._level.size_y):
                x1 = x * 8
                x2 = x1 + 8
                y1 = y * 8
                y2 = y1 + 8

                for entity in self._level.position_system.get_entities_at(x, y):
                    renderable = entity.get(LayoutRenderable)
                    if renderable:
                        tile = renderable.tile
                        break
                else:
                    continue

                # always add floor, because we wanna draw walls above floor
                vertices.extend((x1, y1, x2, y1, x2, y2, x1, y2))
                tex_coords.extend(floor_tex.tex_coords)

                if tile == LayoutGenerator.TILE_WALL:
                    # if we got wall, draw it above floor
                    tex = get_wall_tex(self._level.get_wall_transition(x, y))
                    vertices.extend((x1, y1, x2, y1, x2, y2, x1, y2))
                    tex_coords.extend(tex.tex_coords)

        group = TextureGroup(dungeon_tex, pyglet.graphics.OrderedGroup(Position.ORDER_FLOOR, self._level_group))
        self._level_vlist = self._batch.add(len(vertices) / 2, pyglet.gl.GL_QUADS, group,
            ('v2i/static', vertices),
            ('t3f/statc', tex_coords),
        )

        group = pyglet.graphics.OrderedGroup(Position.ORDER_PLAYER + 1, self._level_group)
        self._light_overlay = LightOverlay(self._level.size_x, self._level.size_y, self._batch, group)
示例#3
0
class RenderSystem(object):

    zoom = 3

    GROUP_LEVEL = pyglet.graphics.OrderedGroup(0)
    GROUP_DIGITS = pyglet.graphics.OrderedGroup(1)
    GROUP_HUD = pyglet.graphics.OrderedGroup(2)

    def __init__(self, level):
        self._level = level
        self._window = level.game.game.window
        self._batch = pyglet.graphics.Batch()
        self._animations = set()
        self._sprites = {}
        self._level_vlist = None
        self._light_overlay = None
        self._last_messages_view = LastMessagesView(level.game.message_log,
                                                    self._window.width,
                                                    self._window.height,
                                                    batch=self._batch,
                                                    group=self.GROUP_HUD)
        self._hud = HUD(batch=self._batch, group=self.GROUP_HUD)
        self._level_group = ZoomGroup(
            self.zoom, CameraGroup(self._window, self.zoom, self.GROUP_LEVEL))
        self._digits_group = CameraGroup(self._window, self.zoom,
                                         self.GROUP_DIGITS)
        self._memory = collections.defaultdict(list)

    def update_player(self):
        player_sprite = self._sprites[self._level.player]
        self._digits_group.focus = player_sprite
        self._level_group.parent.focus = player_sprite
        self._hud.player = self._level.player

    def render_level(self):
        vertices = []
        tex_coords = []

        for x in xrange(self._level.size_x):
            for y in xrange(self._level.size_y):
                x1 = x * 8
                x2 = x1 + 8
                y1 = y * 8
                y2 = y1 + 8

                for entity in self._level.position_system.get_entities_at(
                        x, y):
                    renderable = entity.get(LayoutRenderable)
                    if renderable:
                        tile = renderable.tile
                        break
                else:
                    continue

                # always add floor, because we wanna draw walls above floor
                vertices.extend((x1, y1, x2, y1, x2, y2, x1, y2))
                tex_coords.extend(floor_tex.tex_coords)

                if tile == LayoutGenerator.TILE_WALL:
                    # if we got wall, draw it above floor
                    tex = get_wall_tex(self._level.get_wall_transition(x, y))
                    vertices.extend((x1, y1, x2, y1, x2, y2, x1, y2))
                    tex_coords.extend(tex.tex_coords)

        group = TextureGroup(
            dungeon_tex,
            pyglet.graphics.OrderedGroup(Position.ORDER_FLOOR,
                                         self._level_group))
        self._level_vlist = self._batch.add(
            len(vertices) / 2,
            pyglet.gl.GL_QUADS,
            group,
            ('v2i/static', vertices),
            ('t3f/statc', tex_coords),
        )

        group = pyglet.graphics.OrderedGroup(Position.ORDER_PLAYER + 1,
                                             self._level_group)
        self._light_overlay = LightOverlay(self._level.size_x,
                                           self._level.size_y, self._batch,
                                           group)

    def update_light(self, old_lightmap, new_lightmap):
        # for all changed cells
        for key in set(old_lightmap).union(new_lightmap):
            lit = key in new_lightmap
            memory = self._memory[key]

            # if cell is lit, add it to memory and clear all memory sprites, if there are any
            if lit:
                for sprite in memory:
                    sprite.delete()
                memory[:] = []

            # for every entity in cell
            for entity in self._level.position_system.get_entities_at(*key):
                # set in_fov flag
                # TODO: this doesnt belong to rendering, but i don't want to loop twice
                infov = entity.get(InFOV)
                if infov:
                    infov.in_fov = key in new_lightmap

                # if renderable, manage sprites/memory
                renderable = entity.get(Renderable)
                if not renderable:
                    continue

                # if object is lit, show its sprite
                sprite = self._sprites[entity]
                if lit:
                    sprite.visible = True
                else:
                    sprite.visible = False

                    # if it's memorable, add its current image to the memory
                    if renderable.memorable:
                        pos = entity.get(Position)
                        group = pyglet.graphics.OrderedGroup(
                            pos.order, self._level_group)
                        sprite = pyglet.sprite.Sprite(renderable.image,
                                                      pos.x * 8,
                                                      pos.y * 8,
                                                      batch=self._batch,
                                                      group=group)
                        memory.append(sprite)

        # update light overlay
        self._light_overlay.update_light(new_lightmap, self._memory)

    def add_entity(self, entity):
        image = entity.get(Renderable).image
        pos = entity.get(Position)
        group = pyglet.graphics.OrderedGroup(pos.order, self._level_group)
        sprite = pyglet.sprite.Sprite(image,
                                      pos.x * 8,
                                      pos.y * 8,
                                      batch=self._batch,
                                      group=group)
        self._sprites[entity] = sprite
        entity.listen('image_change', self._on_image_change)
        entity.listen('move', self._on_move)

    def remove_entity(self, entity):
        sprite = self._sprites.pop(entity)
        sprite.delete()
        entity.unlisten('image_change', self._on_image_change)
        entity.unlisten('move', self._on_move)

    def _on_image_change(self, entity):
        self._sprites[entity].image = entity.get(Renderable).image

    def _on_move(self, entity, old_x, old_y, new_x, new_y):
        sprite = self._sprites[entity]
        target_x = new_x * 8
        target_y = new_y * 8

        if not sprite.visible:
            # don't animate invisible sprites
            sprite.set_position(target_x, target_y)
        else:
            start_x = sprite.x
            start_y = sprite.y

            anim = Animation(0.25)

            @anim.event
            def on_update(animation,
                          dt,
                          sprite=sprite,
                          dx=(target_x - start_x),
                          dy=(target_y - start_y)):
                ratio = animation.get_elapsed_ratio()
                x = round(start_x + dx * ratio)
                y = round(start_y + dy * ratio)
                sprite.set_position(x, y)

            @anim.event
            def on_finish(animation, sprite=sprite):
                sprite.set_position(target_x, target_y)

            self.add_animation(anim)

    def draw(self):
        self._window.clear()
        pyglet.gl.glEnable(pyglet.gl.GL_BLEND)
        pyglet.gl.glBlendFunc(pyglet.gl.GL_SRC_ALPHA,
                              pyglet.gl.GL_ONE_MINUS_SRC_ALPHA)
        self._batch.draw()

    def dispose(self):
        for anim in tuple(self._animations):
            anim.cancel()
        assert not self._animations

        for sprite in self._sprites.values():
            sprite.delete()
        self._sprites.clear()

        for sprites in self._memory.values():
            for sprite in sprites:
                sprite.delete()
        self._memory.clear()

        if self._level_vlist:
            self._level_vlist.delete()
            self._level_vlist = None

        if self._light_overlay:
            self._light_overlay.delete()
            self._light_overlay = None

        self._last_messages_view.delete()
        self._hud.delete()

    def add_animation(self, animation):
        self._animations.add(animation)
        animation.push_handlers(on_finish=self._animations.remove)

    def animate_damage(self, x, y, dmg):
        x = (x * 8 + random.randint(2, 6)) * self.zoom
        start_y = (y * 8 + random.randint(0, 4)) * self.zoom

        label = pyglet.text.Label('-' + str(dmg),
                                  font_name='eight2empire',
                                  color=(255, 0, 0, 255),
                                  x=x,
                                  y=start_y,
                                  anchor_x='center',
                                  anchor_y='bottom',
                                  batch=self._batch,
                                  group=self._digits_group)

        anim = Animation(1)

        @anim.event
        def on_update(animation,
                      dt,
                      label=label,
                      start_y=start_y,
                      zoom=self.zoom):
            ratio = animation.get_elapsed_ratio()
            label.y = start_y + 12 * ratio * zoom
            label.color = (255, 0, 0, int((1.0 - ratio) * 255))

        @anim.event
        def on_finish(animation, label=label):
            label.delete()

        self.add_animation(anim)
示例#4
0
文件: render.py 项目: nadako/dungeons
class RenderSystem(object):

    zoom = 3

    GROUP_LEVEL = pyglet.graphics.OrderedGroup(0)
    GROUP_DIGITS = pyglet.graphics.OrderedGroup(1)
    GROUP_HUD = pyglet.graphics.OrderedGroup(2)

    def __init__(self, level):
        self._level = level
        self._window = level.game.game.window
        self._batch = pyglet.graphics.Batch()
        self._animations = set()
        self._sprites = {}
        self._level_vlist = None
        self._light_overlay = None
        self._last_messages_view = LastMessagesView(level.game.message_log, self._window.width, self._window.height, batch=self._batch, group=self.GROUP_HUD)
        self._hud = HUD(batch=self._batch, group=self.GROUP_HUD)
        self._level_group = ZoomGroup(self.zoom, CameraGroup(self._window, self.zoom, self.GROUP_LEVEL))
        self._digits_group = CameraGroup(self._window, self.zoom, self.GROUP_DIGITS)
        self._memory = collections.defaultdict(list)

    def update_player(self):
        player_sprite = self._sprites[self._level.player]
        self._digits_group.focus = player_sprite
        self._level_group.parent.focus = player_sprite
        self._hud.player = self._level.player

    def render_level(self):
        vertices = []
        tex_coords = []

        for x in xrange(self._level.size_x):
            for y in xrange(self._level.size_y):
                x1 = x * 8
                x2 = x1 + 8
                y1 = y * 8
                y2 = y1 + 8

                for entity in self._level.position_system.get_entities_at(x, y):
                    renderable = entity.get(LayoutRenderable)
                    if renderable:
                        tile = renderable.tile
                        break
                else:
                    continue

                # always add floor, because we wanna draw walls above floor
                vertices.extend((x1, y1, x2, y1, x2, y2, x1, y2))
                tex_coords.extend(floor_tex.tex_coords)

                if tile == LayoutGenerator.TILE_WALL:
                    # if we got wall, draw it above floor
                    tex = get_wall_tex(self._level.get_wall_transition(x, y))
                    vertices.extend((x1, y1, x2, y1, x2, y2, x1, y2))
                    tex_coords.extend(tex.tex_coords)

        group = TextureGroup(dungeon_tex, pyglet.graphics.OrderedGroup(Position.ORDER_FLOOR, self._level_group))
        self._level_vlist = self._batch.add(len(vertices) / 2, pyglet.gl.GL_QUADS, group,
            ('v2i/static', vertices),
            ('t3f/statc', tex_coords),
        )

        group = pyglet.graphics.OrderedGroup(Position.ORDER_PLAYER + 1, self._level_group)
        self._light_overlay = LightOverlay(self._level.size_x, self._level.size_y, self._batch, group)

    def update_light(self, old_lightmap, new_lightmap):
        # for all changed cells
        for key in set(old_lightmap).union(new_lightmap):
            lit = key in new_lightmap
            memory = self._memory[key]

            # if cell is lit, add it to memory and clear all memory sprites, if there are any
            if lit:
                for sprite in memory:
                    sprite.delete()
                memory[:] = []

            # for every entity in cell
            for entity in self._level.position_system.get_entities_at(*key):
                # set in_fov flag
                # TODO: this doesnt belong to rendering, but i don't want to loop twice
                infov = entity.get(InFOV)
                if infov:
                    infov.in_fov = key in new_lightmap

                # if renderable, manage sprites/memory
                renderable = entity.get(Renderable)
                if not renderable:
                    continue

                # if object is lit, show its sprite
                sprite = self._sprites[entity]
                if lit:
                    sprite.visible = True
                else:
                    sprite.visible = False

                    # if it's memorable, add its current image to the memory
                    if renderable.memorable:
                        pos = entity.get(Position)
                        group = pyglet.graphics.OrderedGroup(pos.order, self._level_group)
                        sprite = pyglet.sprite.Sprite(renderable.image, pos.x * 8, pos.y * 8, batch=self._batch, group=group)
                        memory.append(sprite)


        # update light overlay
        self._light_overlay.update_light(new_lightmap, self._memory)

    def add_entity(self, entity):
        image = entity.get(Renderable).image
        pos = entity.get(Position)
        group = pyglet.graphics.OrderedGroup(pos.order, self._level_group)
        sprite = pyglet.sprite.Sprite(image, pos.x * 8, pos.y * 8, batch=self._batch, group=group)
        self._sprites[entity] = sprite
        entity.listen('image_change', self._on_image_change)
        entity.listen('move', self._on_move)

    def remove_entity(self, entity):
        sprite = self._sprites.pop(entity)
        sprite.delete()
        entity.unlisten('image_change', self._on_image_change)
        entity.unlisten('move', self._on_move)

    def _on_image_change(self, entity):
        self._sprites[entity].image = entity.get(Renderable).image

    def _on_move(self, entity, old_x, old_y, new_x, new_y):
        sprite = self._sprites[entity]
        target_x = new_x * 8
        target_y = new_y * 8

        if not sprite.visible:
            # don't animate invisible sprites
            sprite.set_position(target_x, target_y)
        else:
            start_x = sprite.x
            start_y = sprite.y

            anim = Animation(0.25)

            @anim.event
            def on_update(animation, dt, sprite=sprite, dx=(target_x - start_x), dy=(target_y - start_y)):
                ratio = animation.get_elapsed_ratio()
                x = round(start_x + dx * ratio)
                y = round(start_y + dy * ratio)
                sprite.set_position(x, y)

            @anim.event
            def on_finish(animation, sprite=sprite):
                sprite.set_position(target_x, target_y)

            self.add_animation(anim)

    def draw(self):
        self._window.clear()
        pyglet.gl.glEnable(pyglet.gl.GL_BLEND)
        pyglet.gl.glBlendFunc(pyglet.gl.GL_SRC_ALPHA, pyglet.gl.GL_ONE_MINUS_SRC_ALPHA)
        self._batch.draw()

    def dispose(self):
        for anim in tuple(self._animations):
            anim.cancel()
        assert not self._animations

        for sprite in self._sprites.values():
            sprite.delete()
        self._sprites.clear()

        for sprites in self._memory.values():
            for sprite in sprites:
                sprite.delete()
        self._memory.clear()

        if self._level_vlist:
            self._level_vlist.delete()
            self._level_vlist = None

        if self._light_overlay:
            self._light_overlay.delete()
            self._light_overlay = None

        self._last_messages_view.delete()
        self._hud.delete()

    def add_animation(self, animation):
        self._animations.add(animation)
        animation.push_handlers(on_finish=self._animations.remove)

    def animate_damage(self, x, y, dmg):
        x = (x * 8 + random.randint(2, 6)) * self.zoom
        start_y = (y * 8 + random.randint(0, 4)) * self.zoom

        label = pyglet.text.Label('-' + str(dmg), font_name='eight2empire', color=(255, 0, 0, 255),
            x=x, y=start_y, anchor_x='center', anchor_y='bottom',
            batch=self._batch, group=self._digits_group)

        anim = Animation(1)

        @anim.event
        def on_update(animation, dt, label=label, start_y=start_y, zoom=self.zoom):
            ratio = animation.get_elapsed_ratio()
            label.y = start_y + 12 * ratio * zoom
            label.color = (255, 0, 0, int((1.0 - ratio) * 255))

        @anim.event
        def on_finish(animation, label=label):
            label.delete()

        self.add_animation(anim)