def create_hallway(self, room1: Rect, room2: Rect, horiz=False) -> None: halls = randint(2, 3) for i in range(0, halls): if not horiz: top = [point for point in room1.points_top] edge_point = top[randrange(0, len(top))] closest_point = edge_point.get_closest_point( [p for p in room2.points]) if room2.with_inset(1).contains( next(edge_point.path_L_to(closest_point))): bottom = [point for point in room1.points_bottom] edge_point = bottom[randrange(0, len(bottom))] closest_point = edge_point.get_closest_point( [p for p in room2.points]) edge_tile = self.cell(edge_point) closest_tile = self.cell(closest_point) self.connect_tiles(edge_tile, closest_tile, manhattan=True) else: right = [point for point in room1.points_right] edge_point = right[randrange(0, len(right))] closest_point = edge_point.get_closest_point( [p for p in room2.points]) if room2.with_inset(1).contains( next(edge_point.path_L_to(closest_point))): left = [point for point in room1.points_left] edge_point = left[randrange(0, len(left))] closest_point = edge_point.get_closest_point( [p for p in room2.points]) edge_tile = self.cell(edge_point) closest_tile = self.cell(closest_point) self.connect_tiles(edge_tile, closest_tile, manhattan=True)
def layout_subviews(self): for i in range(len(self.labels)): is_in_view = self.get_is_in_view(i) if is_in_view: y = 1 + self.frame.y + i - self.min_row self.labels[i].frame = Rect( Point(self.frame.x + 1, y), Size(self.frame.width - self.value_column_width - 2, 1)) self.values[i].frame = Rect( Point( self.frame.x + 1 + self.frame.width - self.value_column_width - 2, y), Size(self.value_column_width, 1)) self.labels[i].is_hidden = not is_in_view self.values[i].is_hidden = not is_in_view
def __init__(self, origin: Point, size: Size): super().__init__(size, cell_class=Empty) self.size = size self.entities = [] self.room_min = self.ROOM_MIN self.room_max = self.ROOM_MAX self.leaf_min = self.LEAF_MIN self.stairs_up = None self.stairs_down = None self.bsp_tree = RandomBSPTree(self.size, self.leaf_min) self.bounds = Rect(origin, size) self.area = self.bounds.with_inset(1) self.generate()
def layout_subviews(self): self.rect_view.apply_springs_and_struts_layout_in_superview() if self.scroll_fraction >= 0: self.scroll_indicator_view.frame = Rect( Point(self.bounds.width - 1, 1 + floor(self.inner_height * self.scroll_fraction)), Size(1, 1)) for i in range(len(self.labels)): is_in_view = self.get_is_in_view(i) if is_in_view: y = 1 + self.bounds.y + i - self.min_row self.labels[i].frame = Rect( Point(self.bounds.x + 1, y), Size(self.bounds.width - self.value_column_width - 2, 1)) self.values[i].frame = Rect( Point(self.bounds.x + 1 + self.bounds.width - self.value_column_width - 2, y), Size(self.value_column_width, 1)) self.labels[i].is_hidden = not is_in_view self.values[i].is_hidden = not is_in_view
def draw(self, ctx): ctx.bkcolor('#000000') ctx.clear_area(self.bounds) current_player_position = self.game_state.level.player.position if current_player_position is not None: self.last_known_player_position = current_player_position half_size = (self.bounds.size / 2).floored draw_game(self.game_state, bounds=Rect(self.last_known_player_position - half_size, self.bounds.size), ctx=ctx)
def __init__(self): self.window = Window() self.message_log = [] self.gutter = [] self.gutter_size = Size( self.window.width - MAP_SIZE.width + MAP_ORIGIN.x, self.window.height - MAP_ORIGIN.y) self.gutter_rect = Rect( Point(self.window.width - self.gutter_size.width, self.window.height - self.gutter_size.height), self.gutter_size) self.log_height = LOG_HEIGHT super().__init__()
def place_room(self, room: Rect, no_floor: bool = False): if not no_floor: for point in room.with_inset(1).points: self.set_cell(FloorTile(point)) for point in room.points_top: self.set_cell(Wall(point, Orientation.HORIZONTAL)) for point in room.points_bottom: self.set_cell(Wall(point, Orientation.HORIZONTAL)) for point in room.points_left: self.set_cell(Wall(point, Orientation.VERTICAL)) for point in room.points_right: self.set_cell(Wall(point, Orientation.VERTICAL)) self.set_cell(Wall(room.origin, Orientation.TOP_LEFT)) self.set_cell(Wall(room.point_top_right, Orientation.TOP_RIGHT)) self.set_cell(Wall(room.point_bottom_right, Orientation.BOTTOM_RIGHT)) self.set_cell(Wall(room.point_bottom_left, Orientation.BOTTOM_LEFT))
def __init__(self, scene: 'GameScene'): self.__floors = {} self._floor_size = self.FLOOR_SIZE self._origin = self.ORIGIN self._center = Point(int(self._floor_size.width / 2), int(self._floor_size.height / 2)) self._view_size = self.VIEW_SIZE self._view_rect = Rect(self._origin, self._view_size) self._view_center = Point(int(self._view_size.width / 2), int(self._view_size.height / 2)) self._current_floor = 0 self.scene = scene for i in range(0, self.FLOORS): self.__floors[i] = Floor(self._origin, self._floor_size) self.populate_floor(self.__floors[i]) for index in self.__floors: floor = self.__floors.get(index + 1) if floor: self.place_stairs(index, index + 1) for floor in self.__floors.values(): if floor.stairs_down and floor.stairs_up: floor.connect_tiles(floor.stairs_down, floor.stairs_up) player_start_tile = self.floor.cell( self.floor.stairs_up.point.get_farthest_point( [tile.point for tile in self.floor.get_open_tiles()])) self.player = Player(player_start_tile, self, self.scene) self.floor.connect_tiles(player_start_tile, self.floor.stairs_up) last_floor = self.get_floor(self.FLOORS - 1) chronotherium_start_tile = last_floor.cell( last_floor.find_open_point()) Chronotherium(chronotherium_start_tile, self, self.scene) last_floor.connect_tiles(chronotherium_start_tile, last_floor.stairs_down)
def _apply_springs_and_struts_layout_to_view(view): options = view.layout_options spec = view.layout_spec superview_bounds = view.superview.bounds fields = [ ('left', 'right', 'x', 'width'), ('top', 'bottom', 'y', 'height'), ] final_frame = Rect(Point(-1000, -1000), Size(-1000, -1000)) for field_start, field_end, field_coord, field_size in fields: debug_string = options.get_debug_string_for_keys( [field_start, field_size, field_end]) matches = (options.get_is_defined(field_start), options.get_is_defined(field_size), options.get_is_defined(field_end)) if matches == (True, True, True): raise ValueError( "Invalid spring/strut definition: {}".format(debug_string)) if matches == (False, False, False): raise ValueError( "Invalid spring/strut definition: {}".format(debug_string)) elif matches == (True, False, False): setattr(final_frame, field_coord, options.get_value(field_start, view)) # pretend that size is constant from frame setattr(final_frame, field_size, getattr(spec, field_size)) elif matches == (True, True, False): setattr(final_frame, field_coord, options.get_value(field_start, view)) setattr(final_frame, field_size, options.get_value(field_size, view)) elif matches == (False, True, False): # magical centering! size_val = options.get_value(field_size, view) setattr(final_frame, field_size, size_val) setattr(final_frame, field_coord, getattr(superview_bounds, field_size) / 2 - size_val / 2) elif matches == (False, True, True): size_val = options.get_value(field_size, view) setattr( final_frame, field_coord, getattr(superview_bounds, field_size) - options.get_value(field_end, view) - size_val) setattr(final_frame, field_size, size_val) elif matches == (False, False, True): setattr( final_frame, field_coord, getattr(superview_bounds, field_size) - options.get_value(field_end, view)) # pretend that size is constant from frame setattr(final_frame, field_size, getattr(spec, field_size)) elif matches == (True, False, True): start_val = options.get_value(field_start, view) end_val = options.get_value(field_end, view) setattr(final_frame, field_coord, start_val) setattr( final_frame, field_size, getattr(superview_bounds, field_size) - start_val - end_val) else: raise ValueError("Unhandled case: {}".format(debug_string)) assert (final_frame.x != -1000) assert (final_frame.y != -1000) assert (final_frame.width != -1000) assert (final_frame.height != -1000) view.frame = final_frame.floored
import weakref from collections import namedtuple from numbers import Real from clubsandwich.geom import Point, Rect, Size from clubsandwich.blt.context import BearLibTerminalContext from .layout_options import LayoutOptions ZERO_RECT = Rect(Point(0, 0), Size(0, 0)) class View: def __init__(self, frame=None, subviews=None, scene=None, layout_options=None): if isinstance(layout_options, dict): # have pity on the user's imports opts = LayoutOptions()._asdict() opts.update(layout_options) layout_options = LayoutOptions(**opts) self._scene = scene self._superview_weakref = lambda: None self.needs_layout = True self._frame = frame or ZERO_RECT self._bounds = self.frame.with_origin(Point(0, 0)) self.subviews = [] self.add_subviews(subviews or []) self.is_first_responder = False self.is_hidden = False
def in_range(self, other): range_rect = Rect(self.position - Point(self._range, self._range), Size(self._range * 2, self._range * 2)) return range_rect.contains(other.position)
def bounds(self) -> Rect: return Rect(self.map.origin, self.map.view_size)
""" Demonstrates BearLibTerminalContext (more convenient rendering) and blt_state """ from clubsandwich.blt.state import blt_state from clubsandwich.blt.context import BearLibTerminalContext from clubsandwich.geom import Rect, Size, Point terminal = BearLibTerminalContext() terminal.open() terminal.bkcolor('#ff0000') # move frame of reference to middle of screen with terminal.translate( (Point(blt_state.width, blt_state.height) / 2).floored): terminal.clear_area(Rect(Point(-1, -1), Size(3, 2))) terminal.refresh() # less verbose than terminal.state(terminal.TK_ESCAPE)! while not blt_state.escape: terminal.read() terminal.close()
class Floor(TileMap): LEAF_MIN = 6 ROOM_MIN = 5 ROOM_MAX = 7 def __init__(self, origin: Point, size: Size): super().__init__(size, cell_class=Empty) self.size = size self.entities = [] self.room_min = self.ROOM_MIN self.room_max = self.ROOM_MAX self.leaf_min = self.LEAF_MIN self.stairs_up = None self.stairs_down = None self.bsp_tree = RandomBSPTree(self.size, self.leaf_min) self.bounds = Rect(origin, size) self.area = self.bounds.with_inset(1) self.generate() def set_cell(self, tile: Tile): try: self._cells[tile.point.x][tile.point.y] = tile tile.floor = self except IndexError: logger.info("Setting cell out of bounds!") return False def get_empty_tiles(self, rect: Rect = None): empty_tiles = [] if rect is not None: for point in rect.points: if isinstance(self.cell(point), Empty): empty_tiles.append(self.cell(point)) else: for cell in self.cells: if isinstance(cell, Empty): empty_tiles.append(cell) return empty_tiles def get_open_tiles(self, rect: Rect = None): open_tiles = [] if rect is not None: for point in rect.points: if self.cell(point).open: open_tiles.append(self.cell(point)) else: for cell in self.cells: if cell.open: open_tiles.append(cell) return open_tiles def find_empty_point(self, rect: Rect = None) -> Point: empty_tiles = self.get_empty_tiles(rect=rect) return empty_tiles[randrange(0, len(empty_tiles))].point def find_open_point(self, rect: Rect = None) -> Point: open_tiles = self.get_open_tiles(rect=rect) return open_tiles[randrange(0, len(open_tiles))].point def connect_tiles(self, tile1: Tile, tile2: Tile, doors: bool = True, manhattan: bool = False): origin = tile1.point dest = origin.get_closest_point( [neighbor for neighbor in tile2.point.neighbors]) self.hallway_tile(origin, doors) if manhattan: for point in origin.path_L_to(dest): self.hallway_tile(point, doors) else: for point in origin.points_bresenham_to(dest): self.hallway_tile(point, doors) self.hallway_tile(dest, doors) def hallway_tile(self, point, doors=True): if isinstance(self.cell(point), Wall): if doors: if any([ neighbor for neighbor in point.neighbors if isinstance(neighbor, Door) ]): return else: tile = Door(point) else: if isinstance(self.cell(point), Door): return else: tile = FloorTile(point) else: tile = FloorTile(point) self.set_cell(tile) def connect_nodes(self, node1: BSPNode, node2: BSPNode, connect_parents: bool = False): if not node1.data.get('connected_to_sibling') or not node2.data.get( 'connected_to_sibling'): room1 = node1.data.get('room') room2 = node2.data.get('room') if room1 and room2: self.create_hallway(room1, room2, horiz=node1.is_horz) else: halls = randint(2, 4) for i in range(0, halls): tile1 = self.cell( self.find_open_point(rect=node1.rect.with_inset(1))) tile2 = self.cell( self.find_open_point(rect=node2.rect.with_inset(1))) self.connect_tiles(tile1, tile2) node1.data['connected_to_sibling'] = True node2.data['connected_to_sibling'] = True if connect_parents: parent1 = node1.parent_weakref() parent2 = node2.parent_weakref() if parent1 and parent2: self.connect_nodes(parent1, parent2) def generate(self): rooms = [] for leaf in self.bsp_tree.root.leaves: room = leaf.rect.get_random_rect( min_size=Size(self.room_min, self.room_min)) leaf.data['room'] = room leaf.data['connected_to_sibling'] = False rooms.append(room) for room in rooms: self.place_room(room) for siblings in self.bsp_tree.root.sibling_pairs: self.connect_nodes(*siblings) for leaf in self.bsp_tree.root.leaves: self.connect_nodes(leaf, next(self.bsp_tree.root.leaves), connect_parents=True) def create_hallway(self, room1: Rect, room2: Rect, horiz=False) -> None: halls = randint(2, 3) for i in range(0, halls): if not horiz: top = [point for point in room1.points_top] edge_point = top[randrange(0, len(top))] closest_point = edge_point.get_closest_point( [p for p in room2.points]) if room2.with_inset(1).contains( next(edge_point.path_L_to(closest_point))): bottom = [point for point in room1.points_bottom] edge_point = bottom[randrange(0, len(bottom))] closest_point = edge_point.get_closest_point( [p for p in room2.points]) edge_tile = self.cell(edge_point) closest_tile = self.cell(closest_point) self.connect_tiles(edge_tile, closest_tile, manhattan=True) else: right = [point for point in room1.points_right] edge_point = right[randrange(0, len(right))] closest_point = edge_point.get_closest_point( [p for p in room2.points]) if room2.with_inset(1).contains( next(edge_point.path_L_to(closest_point))): left = [point for point in room1.points_left] edge_point = left[randrange(0, len(left))] closest_point = edge_point.get_closest_point( [p for p in room2.points]) edge_tile = self.cell(edge_point) closest_tile = self.cell(closest_point) self.connect_tiles(edge_tile, closest_tile, manhattan=True) def get_rect(self) -> Rect: width = randint(self.room_min, self.room_max) height = randint(self.room_min, self.room_max) origin = self.find_empty_point() return Rect(origin, Size(width, height)) def place_room(self, room: Rect, no_floor: bool = False): if not no_floor: for point in room.with_inset(1).points: self.set_cell(FloorTile(point)) for point in room.points_top: self.set_cell(Wall(point, Orientation.HORIZONTAL)) for point in room.points_bottom: self.set_cell(Wall(point, Orientation.HORIZONTAL)) for point in room.points_left: self.set_cell(Wall(point, Orientation.VERTICAL)) for point in room.points_right: self.set_cell(Wall(point, Orientation.VERTICAL)) self.set_cell(Wall(room.origin, Orientation.TOP_LEFT)) self.set_cell(Wall(room.point_top_right, Orientation.TOP_RIGHT)) self.set_cell(Wall(room.point_bottom_right, Orientation.BOTTOM_RIGHT)) self.set_cell(Wall(room.point_bottom_left, Orientation.BOTTOM_LEFT)) def bounds_room(self): for point in self.area.points: self.set_cell(FloorTile(point)) self.place_room(self.bounds, no_floor=True)
def get_rect(self) -> Rect: width = randint(self.room_min, self.room_max) height = randint(self.room_min, self.room_max) origin = self.find_empty_point() return Rect(origin, Size(width, height))