def loop_and_listen_for_scroll_events(self, window, plane, bounds, close): left, right, top, bottom, current_lvl_x, current_lvl_y = bounds mid_screen_x = size()[1] / 2 mid_screen_y = size()[0] / 2 scroll_y = current_lvl_y - mid_screen_y scroll_x = current_lvl_x - mid_screen_x while True: plane.noutrefresh(scroll_y, scroll_x, 0, 0, size()[0] - 1, size()[1] - 1) # For some reason, curses *really* wants the cursor to be below to the # main window, no matter who used it last. Regardless, just move it # to the lower left so it's out of the way. window.move(window.getmaxyx()[0] - 1, 0) window.noutrefresh() curses.doupdate() # Wait around until we get some input. key = sys.stdin.read(1) if key == close or key == "\x1b": break movements = { "k": (0, -1), "j": (0, 1), "h": (-1, 0), "l": (1, 0), "y": (-1, -1), "u": (1, -1), "b": (-1, 1), "n": (1, 1) } move_x, move_y = movements.get(key.lower(), (0, 0)) if key.isupper(): move_x *= 5 move_y *= 5 if move_y > 0: scroll_y = min(scroll_y + move_y, bottom - 5) else: scroll_y = max(scroll_y + move_y, top - size()[0] + 5) if move_x > 0: scroll_x = min(scroll_x + move_x, right - 20) else: scroll_x = max(scroll_x + move_x, left - size()[1] + 20)
def get_plane_for_map(self, levels): # Hopefully 10 lines per dungeon level on average is large enough... max_height = size()[0] * 3 + len(levels) * 10 max_width = size()[1] * 3 return curses.newpad(max_height, max_width)
def display(self, dungeon, window, close="`"): plane = self.get_plane_for_map(dungeon.main()) bounds = self.draw_dungeon(dungeon, plane, plane.getmaxyx()[1] / 2, size()[0]) self.loop_and_listen_for_scroll_events(window, plane, bounds, close)