Example #1
0
    def _setup_tower(self):
        self.tower_origin = (100, 0)
        self.tower = Tower()

        self.room_sprites = set()
        self.groups = set()

        self._setup_rooms()
Example #2
0
class TowerScene(Scene):

    def __init__(self, window_state=None):
        super(TowerScene, self).__init__(window_state)

        self._setup_tower()
        self._setup_status()
        self._setup_player()
        self.move_player_to(0, 0)

        self.bounds = ((0, 0), (0, self.tower.size[1]*self.tower.tile_size[1]+100))

        self.bg_sprites = [
            pyglet.sprite.Sprite(
                pyglet.resource.image('bg.png'),
                x=0, y=0,
                batch=self.bg_batch,
                group=pyglet.graphics.OrderedGroup(-1),
            ),
        ]

        tw, th = self.tower.tile_size
        tx, ty = self.tower.size
        x1, y1 = self.tower_origin
        x2 = self.tower_origin[0] + tx*tw
        y2 = self.tower_origin[1] + ty*th
        self.tower_ghost_shape = self.bg_batch.add(
            4, pyglet.gl.GL_QUADS, pyglet.graphics.OrderedGroup(1),
            ('v2f', [x1, y1, x2, y1, x2, y2, x1, y2]),
            ('c4B', [0, 0, 0, 255] * 4),
        )

    # setup

    def _setup_tower(self):
        self.tower_origin = (100, 0)
        self.tower = Tower()

        self.room_sprites = set()
        self.groups = set()

        self._setup_rooms()

    def _setup_rooms_stupid(self):
        tw, th = self.tower.tile_size
        for room in self.tower.rooms.values():
            s = pyglet.sprite.Sprite(
                room.spec.image,
                x=room.position.x * tw + self.tower_origin[0],
                y=room.position.y * th + self.tower_origin[1],
                batch=self.env_batch,
                group=pyglet.graphics.OrderedGroup(10),
            )
            self.room_sprites.add(s)

    def _setup_rooms(self):
        self.room_group = pyglet.graphics.OrderedGroup(0)
        self.line_of_sight_group = pyglet.graphics.OrderedGroup(1)
        self.stair_group = pyglet.graphics.OrderedGroup(2)
        self.room_groups = {s.identifier:
                            pyglet.graphics.TextureGroup(
                                s.image.get_texture(),
                                parent=self.room_group)
                            for s in self.tower.specs.values()}
        self.room_vertex_lists = {k: {} for k in self.tower.specs.keys()}

    def _setup_player(self):
        self.player_moving = False
        self.player_input = []
        self.player_position = (0, 0)
        self.visible_positions = set()
        self.visible_rooms = {} # room_id: sprite

        self.player_sprite = pyglet.sprite.Sprite(
            pyglet.resource.image('bear.png'),
            x=0, y=0,
            batch=self.object_batch,
            group=pyglet.graphics.OrderedGroup(20),
        )

    def _setup_status(self):
        self.room_label = pyglet.text.Label(
            "", font_name='Monaco',
            font_size=18,
            x=3, y=self.window_state.norm_size[1]-3,
            anchor_x='left', anchor_y='top',
            batch=self.status_batch,
            color=(0, 0, 0, 255)
        )

    # runtime

    def make_room_visible(self, room):
        spec = room.spec
        if room.identifier in self.room_vertex_lists[spec.identifier]:
            return

        tw, th = self.tower.tile_size
        img = spec.image
        texture = img.get_texture()
        texture_group = pyglet.graphics.TextureGroup(
            texture, parent=self.room_group)

        x = room.position.x * tw + self.tower_origin[0]
        y = room.position.y * th + self.tower_origin[1]
        vertices = [
            x, y,
            x + img.width, y,
            x + img.width, y + img.height,
            x, y + img.height,
        ]

        vl_dict = self.room_vertex_lists[spec.identifier]
        vl_dict[room.identifier] = self.env_batch.add(
            4, pyglet.gl.GL_QUADS, texture_group,
            ('v2f', vertices),
            ('t3f', img.tex_coords),
            ('c4B', [255, 255, 255, 90] * 4),
        )

        self._add_stairs_for_room(room)

    def _add_stairs_for_room(self, room):
        tw, th = self.tower.tile_size
        img = pyglet.resource.image('stairs.png')
        texture = img.get_texture()
        texture_group = pyglet.graphics.TextureGroup(
            texture, parent=self.stair_group)

        vertices = []
        stairs = list(self.tower.stairs_for_room(room))
        for sx, sy in stairs:
            x = sx * tw + self.tower_origin[0]
            y = sy * th + self.tower_origin[1]
            vertices.extend([
                x, y,
                x + img.width, y,
                x + img.width, y + img.height,
                x, y + img.height,
            ])

        self.env_batch.add(
            len(stairs) * 4, pyglet.gl.GL_QUADS, texture_group,
            ('v2f', vertices),
            ('t3f', img.tex_coords * len(stairs)),
        )

    def update(self, dt):
        super(TowerScene, self).update(dt)
        self.origin = self.player_sprite.position

    def move_player_to(self, x, y):
        from_position = self.player_position
        to_position = (x, y)

        if self.tower.can_move(from_position, to_position):
            self.player_position = to_position

            to_coords = (
                (x * self.tower.tile_size[0] + self.tower_origin[0]),
                (y * self.tower.tile_size[1] + self.tower_origin[1]),
            )

            if from_position == to_position:
                self.player_moving = False
                self.player_sprite.position = to_coords
            else:
                self.player_moving = True
                self.add_controller(self.player_sprite, 'position',
                                    lerp_2d(self.player_sprite.position,
                                            to_coords,
                                            0.2),
                                    self._move_callback)

            self.current_room = self.tower.room_at_index(*self.player_position)
            self.update_status()

            old_visible_rooms = self.visible_rooms

            self.visible_positions = self.compute_line_of_sight()
            new_rooms = set()
            for position in self.visible_positions:
                room = self.tower.room_at_index(*position)
                new_rooms.add(room)

            self.visible_rooms = {}
            tw, th = self.tower.tile_size
            for room in new_rooms:
                self.make_room_visible(room)
                try:
                    sprite = old_visible_rooms[room.identifier]
                except KeyError:
                    sprite = pyglet.sprite.Sprite(
                        room.spec.image,
                        x=room.position.x * tw + self.tower_origin[0],
                        y=room.position.y * th + self.tower_origin[1],
                        batch=self.env_batch,
                        group=self.line_of_sight_group,
                    )
                self.visible_rooms[room.identifier] = sprite

    def _move_callback(self):
        self.player_moving = False
        self.accept_player_input()

    def compute_line_of_sight(self):
        visible_set = {self.player_position}
        px, py = self.player_position

        def add_while_visible(x, y, dx, dy):
            while True:
                if self.tower.can_move((x, y), (x+dx, y+dy)):
                    visible_set.add((x+dx, y+dy))
                    x += dx
                    y += dy
                else:
                    return

        add_while_visible(px, py, 1, 0)
        add_while_visible(px, py, -1, 0)
        add_while_visible(px, py, 0, 1)
        add_while_visible(px, py, 0, -1)

        return visible_set

    def update_status(self):
        self.room_label.text = self.current_room.name

    def accept_player_input(self):
        if not self.player_input:
            return

        px, py = self.player_position
        symbol = self.player_input[-1]

        if symbol == key.LEFT:
            self.move_player_to(px-1, py)
        elif symbol == key.RIGHT:
            self.move_player_to(px+1, py)
        elif symbol == key.DOWN:
            self.move_player_to(px, py-1)
        elif symbol == key.UP:
            self.move_player_to(px, py+1)

    def on_key_press(self, symbol, modifiers):
        if symbol in (key.LEFT, key.RIGHT, key.UP, key.DOWN):
            self.player_input = [k for k in self.player_input if k != symbol]
            self.player_input.append(symbol)
            if not self.player_moving:
                self.accept_player_input()

    def on_key_release(self, symbol, modifiers):
        if symbol in (key.LEFT, key.RIGHT, key.UP, key.DOWN):
            self.player_input = [k for k in self.player_input if k != symbol]