Пример #1
0
def main():
    screen_width = 90
    screen_height = 60

    tcod.console_set_custom_font(
        'terminal8x12_gs_tc.png',
        tcod.FONT_TYPE_GRAYSCALE | tcod.FONT_LAYOUT_TCOD)
    tcod.console_init_root(screen_width,
                           screen_height,
                           'Spaceship',
                           False,
                           renderer=tcod.RENDERER_SDL2,
                           vsync=True)
    tcod.console_map_ascii_code_to_font(7, 12, 2)
    tcod.console_map_ascii_code_to_font(9, 13, 2)

    object_view_width = 40
    object_view_height = 40

    main_console = Console(screen_width, screen_height, order='F')
    object_console = Console(screen_width, screen_height, order='F')

    parse(all_objects, object_list)

    frame = all_objects['base'][1]

    spaceship_x, spaceship_y = 0, 0

    file_path = getcwd() + '/spaceship.dat'
    if not path.exists(file_path) or path.getsize(file_path) == 0:
        pickle.dump(Object('Spaceship', 50, 50), open(file_path, 'wb+'))

    try:
        spaceship = pickle.load(open(getcwd() + '/spaceship.dat', 'rb'))
    except pickle.UnpicklingError:
        pickle.dump(Object('Spaceship', 50, 50), open(file_path, 'wb+'))
        spaceship = pickle.load(open(file_path, 'rb'))

    examine_x = screen_width - 50
    examine_y = 1
    examine_width = 50
    examine_height = screen_height - 2
    examine_menu = None

    build_menu_object_key_list = ['default']

    for x in range(spaceship.width):
        for y in range(spaceship.height):
            for part in spaceship.tiles[x][y]:
                for object in object_list:
                    if not 'json_id' in part.__dict__ and object.name == part.name:
                        part.json_id = object.json_id
                        print('Assigned {} to {}'.format(
                            part.name, object.json_id))
                    if 'json_id' in part.__dict__ and object.json_id == part.json_id:
                        part.fg = object.fg
                        part.bg = object.bg
                        part.char = object.char
                        part.sorting_index = object.sorting_index
                        part.mass = object.mass
                        break
                else:
                    print(
                        'Could not find corresponding JSON part for existing part {}'
                        .format(part.name))

    spaceship.add_part(0, 0, frame, override=True)

    spaceship.calculate_rooms()

    viewing_mode = 0
    num_modes = len(view_dict) + 2

    selection_index = 0
    max_select_index = 0
    build_menu_open = False
    selection_box = (0, 0), (0, 0)

    screen_offset_x, screen_offset_y = 0, 0

    selection_console = Console(screen_width, screen_height, order='F')
    selection_console.clear(bg=tcod.lightest_blue)

    while True:

        response = None

        prev_select_index = selection_index
        prev_selection_coord = selection_box[0]

        for event in tcod.event.get():
            if event.type == 'KEYDOWN':
                response = {}
                input_resp = handle_input(event)
                if input_resp:
                    response.update(input_resp)
                if build_menu_open and ord('z') >= event.sym >= ord('a'):
                    response['select_item'] = event.sym - ord('a')
            elif event.type == 'MOUSEBUTTONDOWN' or event.type == 'MOUSEBUTTONUP' or event.type == 'MOUSEMOTION':
                response = handle_mouse(event)
            elif event.type == 'QUIT':
                pickle.dump(spaceship, open(file_path, 'wb+'))
                return

        if response:
            if response.get('move'):
                move = response.get('move')
                if examine_menu:
                    examine_menu.selected_index += move[1]
                    if move[0] != 0:
                        if examine_menu.try_change_option(move[0]):
                            spaceship.update_all()
                else:
                    screen_offset_x = max(0, screen_offset_x + move[0])
                    screen_offset_y = max(0, screen_offset_y + move[1])
            elif response.get('viewing_mode'):
                viewing_mode = (viewing_mode +
                                response.get('viewing_mode')) % num_modes
            elif response.get('navigate'):
                selection_index += response.get('navigate')
                if selection_index < 0:
                    selection_index += max_select_index
                elif selection_index >= max_select_index:
                    selection_index -= max_select_index

            if response.get('build'):
                if not build_menu_open:
                    build_menu_open = True
                    build_menu_object_key_list = []
                    selection_index = 0
            if response.get('delete') and not build_menu_open:
                if spaceship.is_valid_coord(
                        selection_box[0][0] - spaceship_x,
                        selection_box[0][1] -
                        spaceship_y) and selection_index < len(
                            spaceship.tiles[selection_box[0][0] - spaceship_x][
                                selection_box[0][1] - spaceship_y]):
                    part_name = spaceship.tiles[
                        selection_box[0][0] -
                        spaceship_x][selection_box[0][1] -
                                     spaceship_y][selection_index].name
                    for x in range(selection_box[0][0], selection_box[1][0]):
                        for y in range(selection_box[0][1],
                                       selection_box[1][1]):
                            for part in spaceship.tiles[x][y]:
                                if part.name == part_name:
                                    spaceship.remove_part(
                                        x - spaceship_x, y - spaceship_y, part)
            elif (response.get('select') or response.get('mouse_move_lheld')
                  or response.get('lclick_down')) and build_menu_open:
                if type(get_object(build_menu_object_key_list)) is list:
                    if response.get('mouse_move_lheld'):
                        selection_box = response.get('mouse_move_lheld'), (
                            response.get('mouse_move_lheld')[0] + 1,
                            response.get('mouse_move_lheld')[1] + 1)
                    for x in range(selection_box[0][0], selection_box[1][0]):
                        for y in range(selection_box[0][1],
                                       selection_box[1][1]):
                            spaceship.add_part(
                                x - spaceship_x, y - spaceship_y,
                                get_object(build_menu_object_key_list)
                                [selection_index])
                else:
                    build_menu_object_key_list.append(
                        list(get_object(build_menu_object_key_list).keys())
                        [selection_index])
                    selection_index = 0
            elif response.get('run'):
                for x in range(spaceship.width):
                    for y in range(spaceship.height):
                        for part in [
                                part for part in spaceship.tiles[x][y]
                                if part.runnable
                        ]:
                            part.runnable.run(spaceship, part, x, y)
                spaceship.update_all()

            if response.get('rclick_down'):
                selection_box = response.get('rclick_down'), response.get(
                    'rclick_down')
            elif response.get('lclick_down'):
                selection_box = response.get('lclick_down'), response.get(
                    'lclick_down')
            elif response.get('mouse_move_rheld'):
                selection_box = selection_box[0], (
                    response.get('mouse_move_rheld')[0] + 1,
                    response.get('mouse_move_rheld')[1] + 1)
            elif response.get(
                    'mouse_move'
            ) and selection_box[1][0] - selection_box[0][
                    0] <= 1 and selection_box[1][1] - selection_box[0][1] <= 1:
                selection_box = response.get('mouse_move'), (
                    response.get('mouse_move')[0] + 1,
                    response.get('mouse_move')[1] + 1)
            elif response.get('select_item') is not None:
                index = response.get('select_item')
                if index < max_select_index:
                    selection_index = index

                    if type(get_object(build_menu_object_key_list)) is dict:
                        build_menu_object_key_list.append(
                            list(
                                get_object(build_menu_object_key_list).keys())
                            [selection_index])
                        selection_index = 0

            if response.get('escape'):
                if build_menu_open:
                    if len(build_menu_object_key_list) == 0:
                        build_menu_open = False
                        selection_index = 0
                    else:
                        build_menu_object_key_list.pop(-1)
                elif examine_menu:
                    examine_menu = None

        if prev_select_index != selection_index or prev_selection_coord != selection_box[
                0]:
            if spaceship.is_valid_coord(
                    selection_box[0][0] - spaceship_x, selection_box[0][1] -
                    spaceship_y) and selection_index < len(
                        spaceship.tiles[selection_box[0][0] - spaceship_x][
                            selection_box[0][1] - spaceship_y]):
                examine_menu = PartMenu(
                    spaceship,
                    spaceship.tiles[selection_box[0][0] -
                                    spaceship_x][selection_box[0][1] -
                                                 spaceship_y][selection_index],
                    examine_width, examine_height, selection_box[0][0],
                    selection_box[0][1])
            else:
                examine_menu = None

        tcod.console_flush()
        main_console.clear(bg=tcod.black)

        selection_pos = selection_box[0]

        object_console.clear()
        render_object(object_console, spaceship, spaceship_x, spaceship_y,
                      viewing_mode)

        object_console.blit(main_console, 0, 0, screen_offset_x,
                            screen_offset_y, object_view_width,
                            object_view_height)

        # main_console.put_char(selection_box[0][0], selection_box[0][1], ord('X'))
        # main_console.fg[selection_box[0][0], selection_box[0][1]] = tcod.cyan
        if build_menu_open:
            iterable = get_object(build_menu_object_key_list)
            if type(iterable) is list:
                iterable = [item.name for item in iterable]
            else:
                iterable = [item.capitalize() for item in iterable]
            for i in range(len(iterable)):
                main_console.print(screen_width - 50,
                                   i,
                                   chr(ord('a') + i) + ' - ' + iterable[i],
                                   bg=(tcod.desaturated_blue if selection_index
                                       == i else tcod.black))
                main_console.fg[screen_width - 50, i] = tcod.light_green
            max_select_index = len(iterable)
        else:
            main_console.print(0, screen_height - 1, str(viewing_mode))
            if spaceship_x <= selection_pos[
                    0] < spaceship_x + spaceship.width and spaceship_y <= selection_pos[
                        1] < spaceship_y + spaceship.height:
                room = spaceship.find_room(selection_pos[0] - spaceship_x,
                                           selection_pos[1] - spaceship_y)
                parts = [
                    part
                    for part in spaceship.tiles[selection_pos[0] -
                                                spaceship_x][selection_pos[1] -
                                                             spaceship_y]
                ]
                if room:
                    gas_y = len(parts) + 2
                    for gas in room.gas_content:
                        main_console.print(
                            20, gas_y, '{1}: {0:.2f} kPa'.format(
                                components.calc_pressure(
                                    room.gas_content[gas], len(room.tiles)),
                                gas.capitalize()))
                        gas_y += 1
                for i in range(len(parts)):
                    part = parts[i]
                    string = part.name

                    if part.gas_grid:
                        string += ' {}'.format(part.gas_grid.index)

                    main_console.print(
                        20,
                        i + 1,
                        string,
                        bg=(tcod.desaturated_blue
                            if selection_index == i else tcod.black))
                max_select_index = len(parts)

            if examine_menu:
                examine_menu.draw()
                examine_menu.console.blit(main_console, examine_x, examine_y,
                                          0, 0, examine_width, examine_height)

        dsel_x = selection_box[1][0] - selection_box[0][0]
        dsel_y = selection_box[1][1] - selection_box[0][1]

        if dsel_x > 0 and dsel_y > 0:
            selection_console.blit(main_console,
                                   selection_box[0][0],
                                   selection_box[0][1],
                                   0,
                                   0,
                                   dsel_x,
                                   dsel_y,
                                   bg_alpha=0.25)

        main_console.blit(tcod.console._root_console,
                          width=screen_width,
                          height=screen_height,
                          bg_alpha=1)
Пример #2
0
    def render(self, console: Console) -> None:
        """
        Renders the map.

        If a tile is in the "visible" array, then draw it with the "light" colors.
        If it isn't, but it's in the "explored" array, then draw it with the "dark" colors.
        Otherwise, the default is "SHROUD".
        """

        # swap color modes depending on mode
        # this is an animation trick. each time we render, move down a row.
        if self.vision_mode and self.vision_row <= self.height:
            self.vision_row += 4
        elif self.vision_row > 0:
            self.vision_row -= 4

        # clamp it
        self.vision_row = min(self.vision_row, self.height)
        self.vision_row = max(self.vision_row, 0)

        # then we do rendering in two passes. 0 to current row, then current_row
        # to rest. so in vision mode, it's 0:0 and we dont' render with vision
        # colors.
        if self.vision_row > 0:
            tiles = np.select(
                condlist=[self.visible, self.explored],
                choicelist=[self.tiles["light_vision"], self.tiles["dark_vision"]],
                default=tile_types.SHROUD,
            )

            console.tiles_rgb[0 : self.width, 0 : self.vision_row] = tiles[0:self.width,0:self.vision_row]

        tiles = np.select(
            condlist=[self.visible, self.explored],
            choicelist=[self.tiles["light"], self.tiles["dark"]],
            default=tile_types.SHROUD,
        )

        # print(f'tiles.shape={tiles.shape}  tiles.shape[][]={tiles[:][self.vision_row:self.height].shape} console.shape={console.tiles_rgb[0 : self.width, self.vision_row : self.height].shape} from {(self.width, self.height)} + row {self.vision_row}')

        console.tiles_rgb[0 : self.width, self.vision_row : self.height] = tiles[0:self.width,self.vision_row:self.height]

        entities_sorted_for_rendering = sorted(
            self.entities, key=lambda x: x.render_order.value
        )

        for entity in entities_sorted_for_rendering:

            # for now, always render all enemies. this will make my life easier.
            # if self.visible[entity.x, entity.y]:
            console.print(
                x=entity.x, y=entity.y, string=entity.char, fg=entity.color
            )

            if self.vision_mode:
                # in case I want to bring back facing
                # console.print(x=entity.x+fx, y=entity.y+fy, string='*', fg=entity.color)

                # now print their facing
                # not sure where to do this but need to map facing to dx/dy.
                LASER_SIGHT_DISTANCE = 4
                # if we're target locked, don't draw facing, draw direct connection
                # if not entity.is_player and entity.target_lock == None:
                #     (fx, fy) = Facing.get_pos(entity.facing)
                #
                #     # get delta to destination
                #     (dx, dy) = (LASER_SIGHT_DISTANCE*fx, LASER_SIGHT_DISTANCE*fy)
                #
                #     cells = tcod.los.bresenham((entity.x, entity.y),
                #         (entity.x + dx, entity.y + dy))
                #
                #     cells = np.delete(cells, 0, 0)
                #
                #     discount = 0.5
                #     for cell in cells:
                #         tile = self.tiles[cell[0]][cell[1]]
                #
                #         if tile['walkable'] or tile['transparent']:
                #             console.print(cell[0], cell[1], string=' ', bg=(int(255*discount), 0, 0))
                #             discount -= 0.5/LASER_SIGHT_DISTANCE

                if not entity.is_player and entity.target_lock != None:
                    cells = tcod.los.bresenham((entity.x, entity.y),
                        (entity.target_lock.x, entity.target_lock.y))

                    cells = np.delete(cells, 0, 0)

                    for cell in cells:
                        tile = self.tiles[cell[0]][cell[1]]

                        if tile['walkable'] or tile['transparent']:
                            console.print(cell[0], cell[1], string=' ', bg=(255, 0, 0))
                elif not entity.is_player and entity.target_lock == None:
                    # if they don't have a lock, paint their entire vision
                    # only compute this for tiles the player can see
                    cells = entity.get_visibility(self.tiles["transparent"])


                    # this is an ndarray with T/F in it. we need to AND this
                    # with a matching size array that has just a white with
                    # alpha channel set. then overlay the whole thing.
                    vision = np.full((self.width, self.height, 3), (255, 0, 0))

                    # I'm not honestly sure why I have to invert this. Need to see if fix is in get_visibility.
                    vision[np.invert(cells)] = [0, 0, 0]
                    vision[np.invert(self.visible[:])] = [0,0,0]

                    vision_console = Console(self.width, self.height, order="F")
                    vision_console.bg_alpha=0.3

                    vision_console.bg[:] = vision

                    # no params since we're fully overlaying the whole screen
                    vision_console.blit(console, bg_alpha=0.2)
Пример #3
0
class Renderer():
    def __init__(self,
                 root_console: Console,
                 ui_manager: UIManager,
                 debug=False):
        self.debug = debug
        self.root_console = root_console
        self.flash_console = None
        self.flash_alpha = 1
        self.width = self.root_console.width
        self.height = self.root_console.height
        self.map_dest_coords = (0, 1)
        self.ui_manager = ui_manager
        self.vision_console = Console(60, 60, 'F')

    def render_level(self,
                     player: Player,
                     entities: list,
                     level_map: BaseMap,
                     colors: bool = True,
                     cursor=None,
                     line: bool = False):
        if self.ui_manager.console:
            self.ui_manager.print_ui()
            self.ui_manager.console.blit(self.root_console,
                                         0,
                                         0,
                                         0,
                                         0,
                                         0,
                                         0,
                                         key_color=tcod.fuchsia)

        if level_map.terrain_console:
            level_map.terrain_console.blit(self.root_console,
                                           self.map_dest_coords[0],
                                           self.map_dest_coords[1],
                                           0,
                                           0,
                                           0,
                                           0,
                                           key_color=tcod.fuchsia)
        if level_map.decor_console:
            level_map.decor_console.blit(self.root_console,
                                         self.map_dest_coords[0],
                                         self.map_dest_coords[1],
                                         0,
                                         0,
                                         0,
                                         0,
                                         key_color=tcod.fuchsia)
        if level_map.living_console:
            level_map.living_console.blit(self.root_console,
                                          self.map_dest_coords[0],
                                          self.map_dest_coords[1],
                                          0,
                                          0,
                                          0,
                                          0,
                                          key_color=tcod.fuchsia)

        #Set FOV
        if not self.debug:
            self.vision_console.bg[:] = tcod.black
            self.vision_console.bg[level_map.fov] = tcod.fuchsia
            self.vision_console.blit(self.root_console,
                                     self.map_dest_coords[0],
                                     self.map_dest_coords[1],
                                     0,
                                     0,
                                     0,
                                     0,
                                     key_color=tcod.fuchsia)

        if not colors:
            self.root_console.fg[:] = tcod.white
            self.root_console.bg[:] = tcod.black

        if self.flash_console:
            self.flash_console.blit(self.root_console, 0, 0, 0, 0,
                                    self.flash_console.width,
                                    self.flash_console.height,
                                    self.flash_alpha, self.flash_alpha)

        if self.ui_manager.popup:
            self.show_popup(*self.ui_manager.popup)
        tcod.console_flush()

    def show_popup(self, title, text, exit_text, centered):
        title_width = self.get_text_width(title)
        text_width = self.get_text_width(text)
        exit_width = self.get_text_width(exit_text)
        min_width = max(title_width, text_width, exit_width)
        min_height = self.get_text_height(text)
        popup_rect = self.calculate_popup_rect(min_width, min_height)
        if centered:
            alignment = tcod.CENTER
        else:
            alignment = tcod.LEFT
        self.root_console.draw_frame(popup_rect[0] - 2,
                                     popup_rect[1] - 2,
                                     popup_rect[2] + 4,
                                     popup_rect[3] + 4,
                                     title,
                                     fg=tcod.white,
                                     bg=tcod.black)
        self.root_console.print_box(popup_rect[0],
                                    popup_rect[1],
                                    popup_rect[2],
                                    popup_rect[3],
                                    text,
                                    fg=tcod.white,
                                    bg=tcod.black,
                                    alignment=alignment)
        self.root_console.print_box(popup_rect[0] + popup_rect[2] - exit_width,
                                    popup_rect[1] + popup_rect[3] + 1,
                                    exit_width,
                                    1,
                                    exit_text,
                                    fg=tcod.white,
                                    bg=tcod.black,
                                    alignment=tcod.RIGHT)

    def get_text_width(self, text):
        lines = text.split('\n')
        width = 0
        for line in lines:
            line_width = len(line)
            if line_width > width:
                width = line_width
        return width

    def get_text_height(self, text):
        lines = text.split('\n')
        return len(lines)

    def calculate_popup_rect(self, width, height):
        hmid = self.width // 2
        vmid = self.height // 2
        popup_hmid = width // 2
        popup_vmid = height // 2
        return (hmid - popup_hmid, vmid - popup_vmid, width, height)

    def flash(self,
              color,
              player,
              entities,
              level_map,
              colors=True,
              cursor=None,
              line=False,
              delay=2):
        self.flash_console = Console(self.root_console.width,
                                     self.root_console.height, 'F')
        delta = timedelta(seconds=delay)
        start = datetime.now()
        diff = timedelta(seconds=0)
        while diff < delta:
            self.flash_alpha = 1 - ((
                (diff.seconds * 1000000) + diff.microseconds) /
                                    (delay * 1000000))
            self.flash_console.draw_rect(0, 0, self.flash_console.width,
                                         self.flash_console.height, ord(' '),
                                         color, color)
            diff = datetime.now() - start
            self.render_level(player,
                              entities,
                              level_map,
                              colors=colors,
                              cursor=cursor,
                              line=line)
        self.flash_console = None
        self.flash_alpha = 1