Пример #1
0
 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
Пример #2
0
 def __init__(self, *args, **kwargs):
     views = [
         LabelView(
             LOGO[1:].rstrip(),
             layout_options=LayoutOptions.row_top(0.5)),
         LabelView(
             "Try resizing the window!",
             layout_options=LayoutOptions.centered('intrinsic', 'intrinsic')),
         ButtonView(
             text="Play", callback=self.play,
             color_bg='#000000', color_fg='#00ff00',
             layout_options=LayoutOptions.row_bottom(4).with_updates(
                 left=0.2, width=0.2, right=None)),
         ButtonView(
             text="Settings", callback=self.show_settings,
             layout_options=LayoutOptions.row_bottom(4).with_updates(
                 left=0.4, width=0.2, right=None)),
         ButtonView(
             text="[color=red]Quit",
             callback=lambda: self.director.pop_scene(),
             # [color=red] messes up auto size calculations
             size=Size(4, 1),
             layout_options=LayoutOptions.row_bottom(4).with_updates(
                 left=0.6, width=0.2, right=None)),
     ]
     super().__init__(views, *args, **kwargs)
Пример #3
0
 def intrinsic_size(self):
     height = 0
     width = 0
     for line in self.text.splitlines():
         height += 1
         width = max(width, len(line))
     return Size(width, height)
Пример #4
0
 def draw(self, ctx):
     ctx.bkcolor(self.color_bg)
     ctx.clear_area(self.bounds)
     frac_width = floor(self.bounds.width * self.fraction)
     ctx.bkcolor(self.color_fg)
     ctx.clear_area(
         self.bounds.with_size(Size(frac_width, self.bounds.height)))
Пример #5
0
 def terminal_update(self, is_active=False):
     terminal.bkcolor('#000000')
     self.view.frame = self.view.frame.with_size(
         Size(blt_state.width, blt_state.height))
     self.view.perform_layout()
     self.view.perform_draw(self.ctx)
     terminal.bkcolor('#000000')
Пример #6
0
 def __init__(self, game, **kwargs):
     super().__init__(fill=True, **kwargs)
     self.game = game
     player = self.game.player
     self.camera = Camera(location=player.location.copy(),
                          screen_size=Size(120, 30))
     self.camera.character_focus = player
     self.game.camera = self.camera
Пример #7
0
    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
Пример #8
0
    def __init__(self, rect, room_type):
        self.room_id = uuid4().hex
        self.room_type = room_type
        # Corridors are always None, rooms are 1-4. Determined by quadrant, i.e.
        # 2nd-topmost ancestor.
        self.difficulty = None

        # If only I had had time to make more room shapes...
        if room_type.shape == EnumRoomShape.BOX_RANDOM:
            self.rect = rect.get_random_rect(Size(5, 5))
        if room_type.shape == EnumRoomShape.BOX_FULL:
            self.rect = rect
Пример #9
0
 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__()
Пример #10
0
    def __init__(self, path):
        self._image = load_xp_file(path)
        self.size = Size(self._image['width'], self._image['height'])
        self.num_layers = self._image['layer_count']

        self._draw_calls_by_layer = []
        for layer_i, layer in enumerate(self._image['layer_data']):
            calls = []
            for x, col in enumerate(layer['cells']):
                for y, cell in enumerate(col):
                    fg = _read_color(cell, 'fore_r', 'fore_g', 'fore_b')
                    bg = self._read_bg_color(layer_i, x, y)
                    calls.append((Point(x, y), cell['keycode'], fg, bg))
            self._draw_calls_by_layer.append(calls)
Пример #11
0
    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)
Пример #12
0
def main():
    terminal.open()
    tilemap = TileMap(Size(80, 24))

    player_pos = Point(0, 0)
    for y, row in enumerate(dungeon):
        for x, char in enumerate(row):
            cell = tilemap[Point(x, y)]
            if char == '.':
                cell.terrain = 0
            elif char == '#':
                cell.terrain = 1
            elif char == '@':
                player_pos = Point(x, y)
            else:
                raise ValueError(char)

    terminal.refresh()
    terminal.clear()
    draw(tilemap, player_pos)
    try:
        while True:
            terminal.clear()
            draw(tilemap, player_pos)
            terminal.refresh()
            if terminal.has_input():
                char = terminal.read()
                if char == terminal.TK_Q:
                    break
                if char == terminal.TK_UP:
                    player_pos = player_pos + Point(0, -1)
                if char == terminal.TK_DOWN:
                    player_pos = player_pos + Point(0, 1)
                if char == terminal.TK_LEFT:
                    player_pos = player_pos + Point(-1, 0)
                if char == terminal.TK_RIGHT:
                    player_pos = player_pos + Point(1, 0)
    except KeyboardInterrupt:
        pass
    finally:
        terminal.close()
Пример #13
0
 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))
Пример #14
0
 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)
Пример #15
0
from clubsandwich.blt.nice_terminal import terminal
from clubsandwich.director import DirectorLoop
from clubsandwich.geom import Size

from main_menu_scene import MainMenuScene

WINDOW_SIZE = Size(80, 46)


class GameLoop(DirectorLoop):
    def terminal_init(self):
        super().terminal_init()
        terminal.set("""
        window.resizeable=true;
        window.size={size.width}x{size.height}
        """.format(size=WINDOW_SIZE))

    def get_initial_scene(self):
        return MainMenuScene()


if __name__ == '__main__':

    GameLoop().run()
Пример #16
0
"""
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()
Пример #17
0
 def intrinsic_size(self):
     return self.label_view.intrinsic_size + Size(4, 0)  # add space for arrows
Пример #18
0
# clubsandwich is my roguelike library that wraps bearlibterminal. We need it
# for some basics which I'll get to in a moment.
from clubsandwich.blt.nice_terminal import terminal
from clubsandwich.director import DirectorLoop
from clubsandwich.geom import Size

# A "scene" is an object that takes over the input and display. The first one
# the player sees is the title screen.
from ld38.main_menu_scene import MainMenuScene

# This is a pathlib.Path object pointing to the game working directory
# containing the executable (and the assets)
from ld38.const import GAME_ROOT


WINDOW_SIZE = Size(100, 46)


# This is a subclass of the clubsandwich game loop object, which takes care of
# a LOT of stuff for us. We just need to do a little configuration to set the
# window size and load the font, and specify what our first scene is.
#
# Once we've provided those things, the DirectorLoop base class will forward
# all input to the active scene, and allow the active scene to draw the screen.
class GameLoop(DirectorLoop):
  def terminal_init(self):
    super().terminal_init()
    terminal.set("""
    window.resizeable=true;
    window.size={size.width}x{size.height};
    font: {root}/assets/NotoMono-Regular.ttf, size=10x16;
Пример #19
0
 def intrinsic_size(self):
     width, height = terminal.measure(self.text)
     return Size(width, height)
Пример #20
0
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
Пример #21
0
 def intrinsic_size(self):
     return Size(len(self.text) + 1, 1)
Пример #22
0
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
Пример #23
0
 def terminal_update(self, is_active=False):
     self.view.frame = self.view.frame.with_size(
         Size(blt_state.width, blt_state.height))
     self.view.perform_layout()
     self.view.perform_draw()
Пример #24
0
WINDOW_WIDTH = 46
WINDOW_HEIGHT = 32
ENCODING = 'utf-8'
SPACING = '1x1'
FONT = resource_path(os.path.join(RESOURCE_PATH, 'VeraMono.ttf'))
SYMBOLA_FONT = resource_path(
    os.path.join(RESOURCE_PATH, 'ttf-symbola/Symbola.ttf'))
SYMBOLA_CODEPAGE = resource_path(
    os.path.join(RESOURCE_PATH, 'symbola_codepage.txt'))
FONT_SIZE = '18x18'
CELL_SIZE = '20x20'
FG_COLOR = Color.BASE1
BG_COLOR = Color.BASE03
# Option to draw UI rectangles
RECTANGLES = False
MAP_SIZE = Size(30, 30)
VIEW_SIZE = Size(20, 20)
MAP_ORIGIN = Point(1, 7)
LOG_HEIGHT = MAP_ORIGIN.y - 1


class Window:

    __instance = None

    def __new__(cls):
        if cls.__instance is None:
            new_window = super().__new__(cls)
            new_window.__init()
            cls.__instance = new_window
        return cls.__instance
Пример #25
0
from clubsandwich.geom import Size

from .level_generator import generate_dungeon
from .level_state import LevelState

LEVEL_SIZE = Size(100, 60)


# Originally, Rogue Basement was going to have several levels. This was going
# to be the object that tracked the current level and let you switch between
# them.
#
# It fulfills that purpose, but there is no actual "change current level"
# method! It would be as simple as setting `self.active_id = NEW_VALUE`.
# The screen is redrawn completely every frame, so there is no need to do
# anything else.
#
# This object also tracks the score. LevelState keeps a weak reference to this
# object, so the active LevelState object is what actually increments the
# score.
class GameState:
    def __init__(self):
        self.level_states_by_id = {}
        self.score = 0
        self.active_id = self.add_level().uuid

    @property
    def level(self):
        return self.level_states_by_id[self.active_id]

    def add_level(self):