def render_entities(self): renderables = self.ecs.manager.entities_with_components('Location', 'Appearance') for r in renderables: location = self.ecs.manager.entities[r]['Location'] appearance = self.ecs.manager.entities[r]['Appearance'] blt.print(location.x, location.y, '[color={}]{}'.format(appearance.color, appearance.char))
def render_map(self): player_loc = self.ecs.manager.entities[self.player]['Location'] self.fov.compute(player_loc.x, player_loc.y, light_walls=True) for x, column in enumerate(self.game_map): for y, tile in enumerate(column): if self.fov.is_visible(x, y): blt.print(x, y, '[color={}]{}'.format( tile.color_lit, tile.char)) self.game_map[x][y].explored = True elif self.game_map[x][y].explored: blt.print(x, y, '[color={}]{}'.format( tile.color_dark, tile.char))
"""test shit""" from bearlibterminal import terminal import os terminal.open() name = "\u2588" * 25 terminal.layer(0) terminal.color(terminal.color_from_argb(255, 255, 0, 0)) #terminal.bkcolor("red") terminal.print(1, 1, name, width=5, height=5) terminal.layer(10) terminal.color("green") terminal.print(1, 2, name, width=5, height=1) terminal.printf( 1, 10, "[color=orange]Welcome[/color][color=red] to the lang zone[/color]") terminal.refresh() x = 10 y = 12 effected_points = [(x + dx, y + dy) for (dx, dy) in ((-1, -1), (-1, 0), (-1, 1), (0, -1), (0, +1), (+1, -1), (+1, 0), (+1, +1))] print(effected_points) print(str(effected_points[0][0]) + " " + str(effected_points[0][1])) print(effected_points[-1]) terminal.layer(20)
def main(): terminal.open() terminal.set("output.vsync=true") terminal.set( "window: title='Plasma Rain', resizeable=true, minimum-size=16x12") terminal.set("window: size={}x{}; font: ".format(INITIAL_SCREEN_WIDTH, INITIAL_SCREEN_LENGTH) + os.path.join(DIR_PATH, '../data/media/lucida.ttf') + ", size={}x{}".format(TILE_WIDTH, TILE_LENGTH)) terminal.set("input.filter= [keyboard+, mouse_move]" ) # Only key release and mouse move trigger state updates terminal.composition(terminal.TK_ON) terminal.bkcolor(terminal.color_from_name("gray")) # grey (or gray), red, flame, orange, amber, yellow, lime, # chartreuse, green, sea, turquoise, cyan, sky, azure, blue, # han, violet, purple, fuchsia, magenta, pink, crimson, transparent terminal.color(terminal.color_from_name("black")) x_speed, y_speed, text_offset = (0, ) * 3 # initialize blank tile_map tile_map: [[[Tile]]] = [[[EMPTY_TILE for _ in range(MAP_WIDTH)] for _ in range(MAP_LENGTH)] for _ in range(MAP_DEPTH)] unit_map: [[[Optional[Unit]]]] = [[[None for _ in range(MAP_WIDTH)] for _ in range(MAP_LENGTH)] for _ in range(MAP_DEPTH)] blueprints = build_blueprints( load_json(os.path.join(mods_dir, "vanilla/blueprints/"), pickle=False)) unit_map[0][0][0] = Unit(blueprint=blueprints['unit']['Human'], armor=blueprints['armor']['Suit'], current_stats=[0, 0, 0, 0, 0], overlay_stats=[0, 0, 0, 0, 0]) zone = load_zone(os.path.join(DIR_PATH, '../data/placeholder/map2.json'), blueprints) paste_zone(zone, tile_map, z=0, y=0) prev_frame_time = time.perf_counter() iterations = 0 # tile_map will only render to screen inside the display, generally set to not overlap with UI # tile_map will only be scrollable between the offset bounds # coordinates are down-right = positive, "opposite" for the offset # set offset_leniency to 1 and you will only be allowed to scroll 1 more tile than enough to see every tile # in general the coordinate system is z, y, x: depth, length, width. No height because it's ambiguous. screen_width, screen_length, display_min_y, display_max_y, display_min_x, display_max_x, \ min_y_offset, max_y_offset, min_x_offset, max_x_offset, x_scroll_leniency, y_scroll_leniency = (0,) * 12 """ Adjusts the bounds defined above, to be called when opening and resizing """ def reset_bounds(): # nonlocal allows modification of outer function's variables nonlocal screen_width, screen_length, display_min_y, display_max_y, display_min_x, display_max_x, \ min_y_offset, max_y_offset, min_x_offset, max_x_offset, y_scroll_leniency, x_scroll_leniency screen_length = terminal.state(terminal.TK_HEIGHT) * TILE_LENGTH screen_width = terminal.state(terminal.TK_WIDTH) * TILE_WIDTH y_scroll_leniency = int(screen_length * SCROLL_LENIENCY) x_scroll_leniency = int(screen_length * SCROLL_LENIENCY) display_min_y = 0 + MARGIN_TOP * TILE_LENGTH display_max_y = screen_length - MARGIN_BOTTOM * TILE_LENGTH display_min_x = 0 + MARGIN_LEFT * TILE_WIDTH display_max_x = screen_width - MARGIN_RIGHT * TILE_WIDTH # TODO convert offsets into actual tile offsets, exclude the complex GUI stuff min_y_offset = min(0, -y_scroll_leniency) max_y_offset = max( 0, -screen_length + MAP_WIDTH * TILE_LENGTH + y_scroll_leniency) min_x_offset = min(0, -x_scroll_leniency) max_x_offset = max( 0, -screen_width + MAP_WIDTH * TILE_WIDTH + x_scroll_leniency) def get_highest_object_if_exists(start_z: int, tile_y: int, tile_x: int, include_tiles: bool = True, include_units: bool = False) -> \ Union[None, Tile, Unit]: if tile_y not in range(0, MAP_WIDTH) or tile_x not in range( 0, MAP_LENGTH): return None for zi in range(start_z, -1, -1): if include_units and unit_map[zi][tile_y][tile_x] is not None: return unit_map[zi][tile_y][tile_x] elif include_tiles and tile_map[zi][tile_y][tile_x] != EMPTY_TILE: return tile_map[zi][tile_y][tile_x] return None reset_bounds() y_offset, x_offset = max(display_min_y, 0), max(0, display_min_x) camera_height = 0 proceed = True while proceed: # t = partial-tile offset in pixels # i = full-tile offset in tiles # c = number of tiles to render ty = y_offset % TILE_LENGTH tx = x_offset % TILE_WIDTH iy = y_offset // TILE_LENGTH ix = x_offset // TILE_WIDTH # vc = screen_length // TILE_SIZE + 1 # hc = screen_width // TILE_SIZE + 1 mouse_x = terminal.state( terminal.TK_MOUSE_X) - x_offset - display_min_x // TILE_WIDTH mouse_y = terminal.state( terminal.TK_MOUSE_Y) - y_offset - display_min_y // TILE_LENGTH x_offset = clamp(x_offset + x_speed, min_x_offset, max_x_offset) y_offset = clamp(y_offset + y_speed, min_y_offset, max_y_offset) terminal.clear() mouse_over_tile = get_highest_object_if_exists(camera_height, mouse_y, mouse_x) mouse_over_tile = mouse_over_tile.blueprint.name if mouse_over_tile is not None else "Empty" mouse_over_unit = get_highest_object_if_exists(camera_height, mouse_y, mouse_x, include_units=True, include_tiles=False) mouse_over_unit = mouse_over_unit.blueprint.name if mouse_over_unit else "Empty" terminal.print(2, 0, "speed: {}, {}".format(x_speed, y_speed)) terminal.print( 2, 1, "offset: {}, {}, height : {}".format(ix, iy, camera_height)) terminal.print( 2, 2, "tile at ({}, {}): {}".format(mouse_x, mouse_y, mouse_over_tile)) terminal.print(2, 3, "unit: {}".format(mouse_over_unit)) higher_tile_already_rendered: [[bool] ] = [[False for _ in range(MAP_WIDTH)] for _ in range(MAP_LENGTH)] # print scrollable map for z in range(camera_height, -1, -1): # top has higher render priority for y in range(0, MAP_LENGTH): for x in range(0, MAP_WIDTH): # s = final coords in pixels sx = (x + ix) * TILE_WIDTH + tx + display_min_x sy = (y + iy) * TILE_LENGTH + ty + display_min_y # render only on-screen tiles if (display_min_y <= sy <= display_max_y and display_min_x <= sx <= display_max_x and not higher_tile_already_rendered[y][x] and (tile_map[z][y][x] != EMPTY_TILE or unit_map[z][y][x] is not None)): if unit_map[z][y][x] is not None: terminal.put_ext(0, 0, sx, sy, unit_map[z][y][x].blueprint.icon) higher_tile_already_rendered[y][x] = True # TODO why is it printing two chars? else: if z < camera_height and tile_map[z][y][ x] != EMPTY_TILE: terminal.put_ext( 0, 0, sx, sy, 0x2588, (terminal.color_from_name('yellow'), terminal.color_from_name('red')) * 4) terminal.put_ext(0, 0, sx, sy, tile_map[z][y][x].blueprint.icon) higher_tile_already_rendered[y][x] = True terminal.refresh() while proceed and terminal.has_input(): key = terminal.read() if key == terminal.TK_CLOSE or key == terminal.TK_ESCAPE: proceed = False elif key == terminal.TK_RESIZED: reset_bounds() elif key == terminal.TK_KP_PLUS: camera_height = clamp(camera_height + 1, 0, MAP_DEPTH - 1) elif key == terminal.TK_KP_MINUS: camera_height = clamp(camera_height - 1, 0, MAP_DEPTH - 1) if terminal.state(terminal.TK_LEFT): if x_speed < SPEED_CAP: x_speed += SPEED_ACCELERATION else: x_speed = SPEED_CAP elif terminal.state(terminal.TK_RIGHT): if x_speed > -SPEED_CAP: x_speed -= SPEED_ACCELERATION else: x_speed = -SPEED_CAP else: x_speed -= sgn(x_speed) if terminal.state(terminal.TK_UP): if y_speed < SPEED_CAP: y_speed += SPEED_ACCELERATION else: y_speed = SPEED_CAP elif terminal.state(terminal.TK_DOWN): if y_speed > -SPEED_CAP: y_speed -= SPEED_ACCELERATION else: y_speed = -SPEED_CAP else: y_speed -= sgn(y_speed) current_time = time.perf_counter() # If twice as slow as desirable warn us, check once every 10 seconds if iterations % ( 10 * FPS ) == 0 and iterations > 0 and current_time - prev_frame_time > 2 / FPS: print( "Lag detected. Desired frame_time: {}; actual frame_time: {}". format(1 / FPS, current_time - prev_frame_time)) prev_frame_time = current_time iterations += 1 terminal.delay(1000 // FPS) terminal.close()
def print(self, *args): if isinstance(args[0], Point): return _terminal.print(args[0].x, args[0].y, *args[1:]) else: return _terminal.print(*args)
def terminal_init(self): terminal.print(0, 1, "Cmd+Q/Alt+F4/whatever to quit")