def _setup_tower(self): self.tower_origin = (100, 0) self.tower = Tower() self.room_sprites = set() self.groups = set() self._setup_rooms()
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]