def help_screen(): T.console_clear(None) CON.default_fg = T.light_grey for i, line in enumerate(HELP_TEXT.split('\n')): CON.print_(1, 1+i, line) T.console_flush() readkey()
def render(self, pokeball: Pokeball, percent_complete: float, message: str) -> libtcod.console: """ Render the area and return the full console """ rows_complete = int(len(CatchGraphicRenderer.graphic) * (percent_complete / 100)) libtcod.console_clear(self.console) libtcod.console_set_default_background(self.console, settings.CATCH_GRAPHIC_BG_COLOR) libtcod.console_set_default_foreground(self.console, settings.LINE_COLOR) libtcod.console_print_frame(self.console, 0, 0, CatchGraphicRenderer.width, CatchGraphicRenderer.height) for y, row in enumerate(CatchGraphicRenderer.graphic): for x, cell in enumerate(row): if cell[0] != '': if len(CatchGraphicRenderer.graphic) - y <= rows_complete: if cell[1] == "upper": color = pokeball.top_color elif cell[1] == "lower": color = pokeball.bottom_color else: color = cell[1] else: color = libtcod.gray libtcod.console_set_default_foreground(self.console, color) libtcod.console_put_char(self.console, x + self.x_offset, y + self.y_offset, cell[0]) if message: libtcod.console_print_rect_ex(self.console, CatchGraphicRenderer.width // 2, CatchGraphicRenderer.height - 3, CatchGraphicRenderer.width - 2, 2, libtcod.BKGND_NONE, libtcod.CENTER, message) return self.console
def render(self, player): libtcod.console_clear(self.console) self._centre_map_on_player(player) self._render_map(player.map_data) self._render_player(player) return self.console
def _draw_status(): con = CON_STATUS T.console_clear(con) con.default_fg = T.light_grey status = status_lines() con.print_(0, 0, '\n'.join(status)) T.console_blit(CON_STATUS, 0, 0, STATUS_W, STATUS_H, None, MAP_W+1, 1)
def __init__(self, width, height, buffered=False): self.width = width self.height = height self._c = tcod.console_new(width, height) self.default_background_color = tcod.black self.default_foreground_color = tcod.white # tcod.console_set_default_background(self._c, tcod.black) # tcod.console_set_default_foreground(self._c, tcod.white) tcod.console_clear(self._c) if buffered: self.buffer = ConsoleBuffer(self)
def title_screen(): T.console_clear(None) for i, txt in enumerate(TITLE_SCREEN): if isinstance(txt, tuple): color, s = txt CON.default_fg = color else: s = txt CON.print_(SCREEN_W//2, i+5, s, alignment=T.CENTER) T.console_flush() readkey()
def initialize_fov(): global fov_recompute, fov_map fov_recompute = True #create the FOV map, according to the generated map fov_map = libtcod.map_new(MAP_WIDTH, MAP_HEIGHT) for y in range(MAP_HEIGHT): for x in range(MAP_WIDTH): libtcod.map_set_properties(fov_map, x, y, not map[x][y].block_sight, not map[x][y].blocked) libtcod.console_clear(con) #unexplored areas start black (which is the default background color)
def render(self, creature: Creature, prev_level: int) -> libtcod.console: """ Returns a full console that can be blitted onto something else anywhere the calling code chooses. """ libtcod.console_clear(self.console) libtcod.console_set_default_background(self.console, settings.LEVEL_UP_BG_COLOR) self._render_lines() self._render_summary(creature, prev_level) self._render_stats(creature, prev_level) return self.console
def _draw_messages(): con = CON_BUFFER n = len(MESSAGES) if n == 0: return start = max(n-BUFFER_H,0) T.console_clear(con) for i in range(start, n): latest, s, color = MESSAGES[i] if not latest: color *= 0.6 con.default_fg = color con.print_(0, i-start, s) T.console_blit(con, 0, 0, SCREEN_W, BUFFER_H, None, 1, MAP_H+1)
def _draw_items(title, items): con = CON_INV T.console_clear(con) con.default_fg = T.white con.print_(1, 0, title) con.default_fg = T.light_grey for i, item in enumerate(items): T.console_put_char_ex(con, 2, i+2, (i+ord('a')), T.light_grey, T.black) c, color = item.glyph T.console_put_char_ex(con, 4, i+2, ord(c), color, T.black) s = item.descr if GAME.player.has_equipped(item): T.console_put_char_ex(con, 0, i+2, ord('*'), T.light_grey, T.black) con.default_fg = T.white else: con.default_fg = T.grey con.print_(6, i+2, s) T.console_blit(con, 0, 0, INV_W, INV_H, None, 1, 1)
def render(self, pokedex, viewing_species, selected_row, selected_column, left_most_column): """ Major external interface to this class. Renders the entire of the pokedex passed in to the console which was originally set on the class. Doesn't blit back onto the main console as this is the job of the caller. """ libtcod.console_clear(self.console) self._render_lines() self._render_selection(selected_row, selected_column, left_most_column) self._render_species(pokedex, left_most_column) if viewing_species: status, species = pokedex[viewing_species] if status > 0: self._render_details_box(species, status) return self.console
def render(self, battle_data: BattleData, messages: List[str], selecting_pokeball: bool) -> libtcod.console: """ The external interface to this class. Call this to render the given battle data object. """ libtcod.console_clear(self.console) self._render_lines() self._render_creature_details(battle_data.defending_creature().creature, BattleRenderer.defending_creature_x, BattleRenderer.defending_creature_y, include_health_values=False) self._render_creature_details(battle_data.player_creature.creature, BattleRenderer.attacking_creature_x, BattleRenderer.attacking_creature_y, include_health_values=True) if selecting_pokeball: self._render_pokeball_select(self.game.game_data.player.available_pokeballs(), x=BattleRenderer.left_padding, y=BattleRenderer.top_section_height + 2) else: self._render_options(battle_data.player_creature.creature, x=BattleRenderer.left_padding, y=BattleRenderer.top_section_height + 2) self._render_blank_message_box(x=BattleRenderer.option_area_width, y=BattleRenderer.top_section_height, width=BattleRenderer.message_area_width, height=BattleRenderer.bottom_section_height) if len(messages): self._render_message(message=messages[0], x=BattleRenderer.option_area_width, y=BattleRenderer.top_section_height + 4) return self.console
def play_game(con, player, entities, animator: Animator, turn_count: int, game_map: GameMap, message_log, game_state, panel, constants): target_x, target_y = player.x, player.y targeting_item = None target_entity = None while True: fov_algorithm = 2 fov_light_walls = True fov_radius = 20 fov_recompute = True fov_map = initialize_fov(game_map) if fov_recompute: recompute_fov(fov_map, player.x, player.y, fov_radius, fov_light_walls, fov_algorithm) render_all(con, panel, entities, animator, player, game_map, fov_map, fov_recompute, message_log, constants['screen_width'], constants['screen_height'], constants['bar_width'], constants['panel_height'], constants['panel_y'], game_state, target_x, target_y, target_entity, turn_count) tcod.console_flush() clear_all(con, entities) player_turn_results = [] animator.advance_frame() # Handle Game State if game_state == GameStates.ENEMY_TURN: turn_count += 1 # Generate path map with all static tiles (ignore entities for now) path_map = generate_path_map(game_map, entities=None, player=player) for entity in entities: if entity.ai and entity.ai != Player: recompute_walkable(fov_map, game_map, entities, entity) entity_turn_results = entity.ai.take_turn( player, fov_map, game_map, entities, path_map) for entity_turn_result in entity_turn_results: message = entity_turn_result.get('message') dead_entity = entity_turn_result.get('dead') if message: message_log.add_message(message) if dead_entity: if dead_entity == player: message, game_state = kill_player(player) else: message = kill_entity(dead_entity) message_log.add_message(message) if game_state == GameStates.PLAYER_DEAD: break if game_state == GameStates.PLAYER_DEAD: break else: game_state = GameStates.PLAYER_TURN # Handle Events for event in tcod.event.wait(): if event.type == "QUIT": save_game(player, entities, animator, turn_count, game_map, message_log, game_state) raise SystemExit() if event.type == "KEYDOWN": action: [Action, None] = handle_keys(event.sym, game_state) if action is None: continue action_type: ActionType = action.action_type if action_type == ActionType.EXECUTE: if game_state == GameStates.TARGETING: item_use_results = player.body.use_selected_appendage( entities=entities, fov_map=fov_map, game_map=game_map, target_x=target_x, target_y=target_y) player_turn_results.extend(item_use_results) game_state = GameStates.ENEMY_TURN elif game_state == GameStates.LOOKING: look_results = [] looked_at_entities = get_entities_at_location( entities, target_x, target_y) if tcod.map_is_in_fov(fov_map, target_x, target_y): if looked_at_entities: for entity in looked_at_entities: look_results.extend( entity.get_description()) target_entity = entity else: if game_map.tiles[target_x][target_y].blocked: look_results.append({ 'message': Message("You stare at the wall.") }) else: look_results.append({ 'message': Message("You stare into empty space.") }) else: look_results.append({ 'message': Message("You can't see that far.") }) game_state = GameStates.PLAYER_TURN player_turn_results.extend(look_results) if action_type == ActionType.MOVEMENT: dx: int = action.kwargs.get("dx", 0) dy: int = action.kwargs.get("dy", 0) # Player Movement if game_state == GameStates.PLAYER_TURN: destination_x = player.x + dx destination_y = player.y + dy tile_results = game_map.tiles[destination_x][ destination_y].overlap_entity(player) player_turn_results.extend(tile_results) if not game_map.is_blocked(destination_x, destination_y): target_appendage = get_blocking_entities_at_location( entities, destination_x, destination_y) if target_appendage: if target_appendage.body: player_fighter = player.body.selected_appendage.fighter if player_fighter: target_entity = target_appendage game_state = GameStates.TARGET_APPENDAGE else: player_turn_results.append({ 'message': Message( "You cannot attack with your {0}." .format( player.body. selected_appendage.name), tcod.yellow) }) elif target_appendage.structure: structure_interact_results = target_appendage.structure.interact( player) player_turn_results.extend( structure_interact_results) else: player.move(dx, dy) else: player_turn_results.append({ 'message': Message("You slam yourself into the wall!", tcod.orange) }) if game_state != GameStates.TARGET_APPENDAGE: game_state = GameStates.ENEMY_TURN # Targeting elif game_state in (GameStates.TARGETING, GameStates.LOOKING): new_x = target_x + dx new_y = target_y + dy if player.distance(new_x, new_y) < targeting_radius: target_x = new_x target_y = new_y elif action_type == ActionType.GRAB: for entity in entities: if entity.item and entity.x == player.x and entity.y == player.y: pickup_result = player.body.grab_entity(entity) player_turn_results.extend(pickup_result) break else: player_turn_results.append({ 'message': Message('You grab at the air', tcod.yellow) }) game_state = GameStates.ENEMY_TURN elif action_type == ActionType.LOOK: game_state = GameStates.LOOKING target_x, target_y = player.x, player.y targeting_radius = 100 elif action_type == ActionType.WAIT: player_turn_results.append({ 'message': Message('You stare blankly into space', tcod.yellow) }) game_state = GameStates.ENEMY_TURN elif action_type == ActionType.CHOOSE_OPTION: option_index = action.kwargs.get("option_index", None) if game_state == GameStates.SWAP_APPENDAGE: if option_index < len(player.body.appendages): item = player.body.appendages[option_index] swap_results = player.body.select_appendage(item) player_turn_results.extend(swap_results) game_state = GameStates.PLAYER_TURN elif game_state == GameStates.TARGET_APPENDAGE: if option_index < len(target_entity.body.appendages): target_appendage = target_entity.body.appendages[ option_index] attack_results = player.body.selected_appendage.fighter.attack_appendage( target_appendage) player_turn_results.extend(attack_results) game_state = GameStates.ENEMY_TURN elif action_type == ActionType.INTERACT: for entity in entities: if entity.structure and entity.x == player.x and entity.y == player.y: interact_results = entity.structure.interact( player) player_turn_results.extend(interact_results) break else: if game_state == GameStates.PLAYER_TURN: activate_item_results = player.body.use_selected_appendage( fov_map=fov_map, game_map=game_map, entities=entities) if activate_item_results: player_turn_results.extend( activate_item_results) game_state = GameStates.ENEMY_TURN elif action_type == ActionType.DROP_INVENTORY_ITEM: grabber = player.body.selected_appendage.grabber if grabber: player_turn_results.extend(grabber.drop()) # game_state = GameStates.DROP_INVENTORY elif action_type == ActionType.SWAP_APPENDAGE: game_state = GameStates.SWAP_APPENDAGE elif action_type == ActionType.ESCAPE: if game_state == GameStates.TARGETING: game_state = GameStates.PLAYER_TURN elif game_state == GameStates.PLAYER_TURN: save_game(player, entities, animator, turn_count, game_map, message_log, game_state) main() elif action_type == ActionType.RESTART: main() # Process player turn results for player_turn_result in player_turn_results: message = player_turn_result.get('message') dead_entity = player_turn_result.get('dead') item_added = player_turn_result.get('item_added') item_consumed = player_turn_result.get('consumed') item_dropped = player_turn_result.get('item_dropped') targeting = player_turn_result.get('targeting') next_floor = player_turn_result.get('next_floor') if message: message_log.add_message(message) if dead_entity: if dead_entity == player: message, game_state = kill_player(player) else: message_log.add_message(kill_entity(dead_entity)) if item_added: entities.remove(item_added) game_state = GameStates.ENEMY_TURN if item_dropped: entities.append(item_dropped) game_state = GameStates.ENEMY_TURN if targeting: game_state = GameStates.TARGETING targeting_item = targeting targeting_radius = targeting.item.targeting_radius target_x = player.x target_y = player.y message_log.add_message( Message("You begin aiming the {0}.".format( targeting.name))) # TODO: Replace occurrences of add_message with player_turn_result approach # player_turn_results.append({'message': Message("You begin aiming the {0}.".format(targeting.name))}) if next_floor: entities = game_map.next_floor(player, constants) fov_map = initialize_fov(game_map) tcod.console_clear(con)
def main(): # pull variables constants = get_constants() # set graphics template (source, type, layout) # --- original setup --- # libtcod.console_set_custom_font( # 'arial10x10.png', # libtcod.FONT_TYPE_GRAYSCALE | libtcod.FONT_LAYOUT_TCOD) # --- new font file --- libtcod.console_set_custom_font( 'TiledFont.png', libtcod.FONT_TYPE_GREYSCALE | libtcod.FONT_LAYOUT_TCOD, 32, 10) # create screen (width, height, title, fullscreen_boolean) libtcod.console_init_root(constants['screen_width'], constants['screen_height'], constants['window_title'], False) # initialize console con = libtcod.console_new(constants['screen_width'], constants['screen_height']) panel = libtcod.console_new(constants['screen_width'], constants['panel_height']) player = None entities = [] game_map = None message_log = None game_state = None show_main_menu = True show_load_error_message = False main_menu_background_image = libtcod.image_load('menu_background.png') key = libtcod.Key() mouse = libtcod.Mouse() libtcod.console_set_fullscreen(True) # mixer.music.play(-1) # music_loop = mixer.Sound('Cave_Loop.wav') # mixer.Sound.play(music_loop) mixer.init() music_loop = mixer.Sound('Cave_Loop.wav') mixer.Sound.play(music_loop, loops=-1) while not libtcod.console_is_window_closed(): libtcod.sys_check_for_event( libtcod.EVENT_KEY_PRESS | libtcod.EVENT_MOUSE, key, mouse) if show_main_menu: main_menu(con, main_menu_background_image, constants['screen_width'], constants['screen_height']) if show_load_error_message: message_box(con, 'No save game to load', 50, constants['screen_width'], constants['screen_height']) libtcod.console_flush() action = handle_main_menu(key) new_game = action.get('new_game') load_saved_game = action.get('load_game') exit_game = action.get('exit') if show_load_error_message and (new_game or load_saved_game or exit_game): show_load_error_message = False elif new_game: player, entities, game_map, message_log, game_state = get_game_variables( constants) game_state = GameStates.PLAYER_TURN show_main_menu = False elif load_saved_game: try: player, entities, game_map, message_log, game_state = load_game( ) show_main_menu = False except FileNotFoundError: show_load_error_message = True elif exit_game: break else: libtcod.console_clear(con) play_game(player, entities, game_map, message_log, game_state, con, panel, constants) show_main_menu = True
def render_all(): global fov_map, color_dark_wall, color_light_wall global color_dark_ground, color_light_ground global fov_recompute if fov_recompute: # recompute FOV if needed (the player moved or something) fov_recompute = False tcod.map_compute_fov(fov_map, player.x, player.y, TORCH_RADIUS, FOV_LIGHT_WALLS, FOV_ALGO) # go through all tiles, and set their background color according to the FOV for y in range(MAP_HEIGHT): for x in range(MAP_WIDTH): visible = tcod.map_is_in_fov(fov_map, x, y) wall = map[x][y].block_sight if EXPLORE_MODE: if not visible: # it's out of the player's FOV if map[x][y].explored: if wall: tcod.console_set_char_background(con, x, y, color_dark_wall, tcod.BKGND_SET) else: tcod.console_set_char_background(con, x, y, color_dark_ground, tcod.BKGND_SET) else: # it's visible if wall: tcod.console_set_char_background(con, x, y, color_light_wall, tcod.BKGND_SET) else: tcod.console_set_char_background(con, x, y, color_light_ground, tcod.BKGND_SET) map[x][y].explored = True else: if not visible: # it's out of the player's FOV if wall: tcod.console_set_char_background(con, x, y, color_dark_wall, tcod.BKGND_SET) else: tcod.console_set_char_background(con, x, y, color_dark_ground, tcod.BKGND_SET) else: # it's visible if wall: tcod.console_set_char_background(con, x, y, color_light_wall, tcod.BKGND_SET) else: tcod.console_set_char_background(con, x, y, color_light_ground, tcod.BKGND_SET) # draw all objects in the list for object in objects: if object != player: object.draw() player.draw() # blit the contents of "con" to the root console tcod.console_blit(con, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0, 0) # GUI tcod.console_set_default_background(panel, tcod.black) tcod.console_clear(panel) message_y = 1 for (line, color) in game_msgs: tcod.console_set_default_foreground(panel, color) tcod.console_print_ex(panel, MSG_X, message_y, tcod.BKGND_NONE, tcod.LEFT, line) message_y += 1 tcod.console_set_default_foreground(panel, tcod.light_gray) name = get_names_under_mouse() print(name) tcod.console_print_ex(panel, 1, 0, tcod.BKGND_NONE, tcod.LEFT, name) render_bar(1, 1, BAR_WIDTH, "HP", player.fighter.hp, player.fighter.max_hp, tcod.light_red, tcod.darker_red) tcod.console_blit(panel, 0, 0, SCREEN_WIDTH, PANEL_HEIGHT, 0, 0, PANEL_Y)
def test_console_defaults(console, fg, bg): libtcodpy.console_set_default_foreground(console, fg) libtcodpy.console_set_default_background(console, bg) libtcodpy.console_clear(console) assert_char(console, 0, 0, None, fg, bg)
player = Player(WIDTH // 3, HEIGHT // 2, '@', tcod.white, 'The Hero') full_dungeon_stack = dict() # i want to save all previously generated levels so the player can go back to them. dict so we can have the freedom to make level 8 before 5,6,7 if we need to. full_dungeon_stack[0] = dungeon_level(0) # full_dungeon_stack[0].map would be town. full_dungeon_stack[0].creatures.append(player) current_level = 0 # level zero is a special starting area. # Initialize the root console in a context. with tcod.console_init_root(WIDTH, HEIGHT, 'tcod-test', False) as root_console: MM = MonsterManager(root_console) tcod.sys_set_fps(24) state = 'main' # set back to a main menu when we get there. while not tcod.console_is_window_closed(): tcod.console_clear(root_console) # clear screen between frames. # if state is 'start' blit the opening screen asking the player to start a new game. if(state == 'start'): tcod.console_flush() ev = tcod.sys_wait_for_event(tcod.EVENT_ANY, key, None, True) if ev & tcod.EVENT_KEY: state = 'main' # if state is 'main' blit the map and the player on the screen as well as the noise level. elif(state == 'main'): # figure out what level we are on and use that data to display. try: _level = full_dungeon_stack[current_level] except KeyError: full_dungeon_stack[current_level] = dungeon_level(current_level)
def render_all(): global fov_map, color_dark_wall, color_light_wall global color_dark_ground, color_light_ground global fov_recompute if fov_recompute: #recompute FOV if needed (the player moved or something) fov_recompute = False libtcod.map_compute_fov(fov_map, player.x, player.y, TORCH_RADIUS, FOV_LIGHT_WALLS, FOV_ALGO) #go through all tiles, and set their background color according to the FOV for y in range(MAP_HEIGHT): for x in range(MAP_WIDTH): visible = libtcod.map_is_in_fov(fov_map, x, y) wall = map[x][y].block_sight if not visible: #if it's not visible right now, the player can only see it if it's explored if map[x][y].explored: if wall: libtcod.console_set_char_background( con, x, y, color_dark_wall, libtcod.BKGND_SET) else: libtcod.console_set_char_background( con, x, y, color_dark_ground, libtcod.BKGND_SET) else: #it's visible if wall: libtcod.console_set_char_background( con, x, y, color_light_wall, libtcod.BKGND_SET) else: libtcod.console_set_char_background( con, x, y, color_light_ground, libtcod.BKGND_SET) #since it's visible, explore it map[x][y].explored = True #draw all objects in the list, except the player. we want it to #always appear over all other objects! so it's drawn later. for object in objects: if object != player: object.draw() player.draw() #blit the contents of "con" to the root console libtcod.console_blit(con, 0, 0, MAP_WIDTH, MAP_HEIGHT, 0, 0, 0) #prepare to render the GUI panel libtcod.console_set_default_background(panel, libtcod.black) libtcod.console_clear(panel) #print the game messages, one line at a time y = 1 for (line, color) in game_msgs: libtcod.console_set_default_foreground(panel, color) libtcod.console_print_ex(panel, MSG_X, y, libtcod.BKGND_NONE, libtcod.LEFT, line) y += 1 #show the player's stats render_bar(1, 1, BAR_WIDTH, 'HP', player.fighter.hp, player.fighter.max_hp, libtcod.light_red, libtcod.darker_red) libtcod.console_print_ex(panel, 1, 3, libtcod.BKGND_NONE, libtcod.LEFT, 'Dungeon level ' + str(dungeon_level)) #display names of objects under the mouse libtcod.console_set_default_foreground(panel, libtcod.light_gray) libtcod.console_print_ex(panel, 1, 0, libtcod.BKGND_NONE, libtcod.LEFT, get_names_under_mouse()) #blit the contents of "panel" to the root console libtcod.console_blit(panel, 0, 0, SCREEN_WIDTH, PANEL_HEIGHT, 0, 0, PANEL_Y)
def main(): """Main function for the game.""" constants = get_constants() # setup Font font_path = '/home/bobbias/roguelike/arial10x10.png' font_flags = tcod.FONT_TYPE_GREYSCALE | tcod.FONT_LAYOUT_TCOD tcod.console_set_custom_font(font_path, font_flags) # init screen # window_title = 'Python 3 libtcod tutorial' con = tcod.console_init_root(constants['screen_width'], constants['screen_height'], order='F', renderer=tcod.RENDERER_OPENGL2) panel = tcod.console_new(constants['screen_width'], constants['panel_height']) player = None entities = [] game_map = None message_log = None game_state = None show_main_menu = True show_load_error_message = False main_menu_background_imgage = tcod.image_load('menu_background.png') key = tcod.Key() mouse = tcod.Mouse() while not tcod.console_is_window_closed(): tcod.sys_check_for_event(tcod.EVENT_KEY_PRESS | tcod.EVENT_MOUSE, key, mouse) if show_main_menu: main_menu(con, main_menu_background_imgage, constants['screen_width'], constants['screen_height']) if show_load_error_message: message_box(con, 'No save game to load!', 50, constants['screen_width'], constants['screen_height']) tcod.console_flush() action = handle_main_menu(key) new_game = action.get('new_game') load_saved_game = action.get('load_saved_game') exit_game = action.get('exit') if show_load_error_message and (new_game or load_saved_game or exit_game): show_load_error_message = False elif new_game: player, entities, game_map, message_log, game_state = get_game_variables( constants) game_state = GameStates.PLAYERS_TURN show_main_menu = False elif load_saved_game: try: player, entities, game_map, message_log, game_state = load_game( ) show_main_menu = False except FileNotFoundError: show_load_error_message = True elif exit_game: break else: tcod.console_clear(con) play_game(player, entities, game_map, message_log, game_state, con, panel, constants) show_main_menu = True
def render_all(con, panel, entities, player, game_map, fov_map, fov_recompute, message_log, screen_width, screen_height, bar_width, panel_height, panel_y, mouse, colors, game_state): # draw all tiles in the game map # loop through each tile in the game map and check if it blocks sight or not if fov_recompute: for y in range(game_map.height): for x in range(game_map.width): visible = libtcod.map_is_in_fov(fov_map, x, y) wall = game_map.tiles[x][y].block_sight if visible: # if tile is visible, it will be drawn in the "light" colors # if blocks sight, draw as a wall if wall: libtcod.console_set_char_background( con, x, y, colors.get('light_wall'), libtcod.BKGND_SET) # if does not block sight, draw as a floor else: libtcod.console_set_char_background( con, x, y, colors.get('light_ground'), libtcod.BKGND_SET) # mark tiles within the player's field of view as explored game_map.tiles[x][y].explored = True elif game_map.tiles[x][ y].explored: # tile is not within FOV - however, if the tile has already been explored, draw it as a "dark" tile # if blocks sight, draw as a wall if wall: libtcod.console_set_char_background( con, x, y, colors.get('dark_wall'), libtcod.BKGND_SET) # if does not block sight, draw as a floor else: libtcod.console_set_char_background( con, x, y, colors.get('dark_ground'), libtcod.BKGND_SET) entities_in_render_order = sorted(entities, key=lambda x: x.render_order.value) # draw all entities in the list for entity in entities_in_render_order: draw_entity(con, entity, fov_map, game_map) libtcod.console_blit(con, 0, 0, screen_width, screen_height, 0, 0, 0) libtcod.console_set_default_background(panel, libtcod.black) libtcod.console_clear(panel) # print the game messages, one line at a time y = 1 for message in message_log.messages: libtcod.console_set_default_foreground(panel, message.color) libtcod.console_print_ex(panel, message_log.x, y, libtcod.BKGND_NONE, libtcod.LEFT, message.text) y += 1 render_bar(panel, 1, 1, bar_width, 'HP', player.fighter.hp, player.fighter.max_hp, libtcod.light_red, libtcod.darker_red) libtcod.console_print_ex( panel, 1, 3, libtcod.BKGND_NONE, libtcod.LEFT, 'Dungeon level: {0}'.format(game_map.dungeon_level)) libtcod.console_set_default_foreground(panel, libtcod.light_gray) libtcod.console_print_ex(panel, 1, 0, libtcod.BKGND_NONE, libtcod.LEFT, get_names_under_mouse(mouse, entities, fov_map)) libtcod.console_blit(panel, 0, 0, screen_width, panel_height, 0, 0, panel_y) if game_state in (GameStates.SHOW_INVENTORY, GameStates.DROP_INVENTORY): if game_state == GameStates.SHOW_INVENTORY: inventory_title = 'Press the key next to an item to use it, or Esc to cancel.\n' else: inventory_title = 'Press the key next to an item to drop it, or Esc to cancel.\n' inventory_menu(con, inventory_title, player.inventory, 50, screen_width, screen_height) elif game_state == GameStates.LEVEL_UP: level_up_menu(con, 'Level up! Choose a state to raise:', player, 40, screen_width, screen_height) elif game_state == GameStates.CHARACTER_SCREEN: character_screen(player, 30, 10, screen_width, screen_height)
def render_all( con, panel, entities, player, game_map, fov_map, fov_recompute, message_log, screen_width, screen_height, bar_width, panel_height, panel_y, mouse, colors, game_state, ): """ Dra all entities in the list :param con: Console window to draw on :param panel: Console window for the stats information :param entities: List of entities to draw :param player: Player character class :param game_map: GameMap object :param fov_map: Field of View map :param fov_recompute: Boolean flag to determine if FOV should be recomputed :param message_log: MessageLog object with Messages :param screen_width: Width of the screen :param screen_height: Height of the screen :param bar_width: Width of the health bar :param panel_height: Height of the panel :param panel_y: Placement of the panel with respect to the main console window :param mouse: Mouse pointer object :param colors: GameMap color values :param game_state: GameState :return: None """ # Draw all the tiles in the game map if fov_recompute: for y in range(game_map.height): for x in range(game_map.width): visible = tcod.map_is_in_fov(fov_map, x, y) wall = game_map.tiles[x][y].block_sight if visible: if wall: tcod.console_set_char_background( con, x, y, colors.get("light_wall"), tcod.BKGND_SET) else: tcod.console_set_char_background( con, x, y, colors.get("light_ground"), tcod.BKGND_SET) game_map.tiles[x][y].explored = True elif game_map.tiles[x][y].explored: if wall: tcod.console_set_char_background( con, x, y, colors.get("dark_wall"), tcod.BKGND_SET) else: tcod.console_set_char_background( con, x, y, colors.get("dark_ground"), tcod.BKGND_SET) # Draw all entities in the list entities_in_render_order = sorted(entities, key=lambda e: e.render_order.value) for entity in entities_in_render_order: draw_entity(con, entity, fov_map, game_map) tcod.console_blit(con, 0, 0, screen_width, screen_height, 0, 0, 0) tcod.console_set_default_background(panel, tcod.black) tcod.console_clear(panel) # Print the game messages, one line at a time y = 1 for message in message_log.messages: tcod.console_set_default_foreground(panel, message.color) tcod.console_print_ex(panel, message_log.x, y, tcod.BKGND_NONE, tcod.LEFT, message.text) y += 1 render_bar( panel, 1, 1, bar_width, "HP", player.fighter.hp, player.fighter.max_hp, tcod.light_red, tcod.darker_red, ) tcod.console_print_ex( panel, 1, 3, tcod.BKGND_NONE, tcod.LEFT, f"Dungeon level: {game_map.dungeon_level}", ) tcod.console_set_default_foreground(panel, tcod.light_gray) tcod.console_print_ex( panel, 1, 0, tcod.BKGND_NONE, tcod.LEFT, get_names_under_mouse(mouse, entities, fov_map), ) tcod.console_blit(panel, 0, 0, screen_width, panel_height, 0, 0, panel_y) if game_state in (GameStates.SHOW_INVENTORY, GameStates.DROP_INVENTORY): if game_state == GameStates.SHOW_INVENTORY: inventory_title = ( "Press the key next to an item to use it, or ESC to cancel.\n") else: inventory_title = ( "Press the key next to an item to drop it, or ESC to cancel.\n" ) inventory_menu(con, inventory_title, player, 50, screen_width, screen_height) elif game_state == GameStates.LEVEL_UP: level_up_menu( con, "Level up! Choose a stat to raise:", player, 40, screen_width, screen_height, ) elif game_state == GameStates.CHARACTER_SCREEN: character_screen(player, 30, 10, screen_width, screen_height)
def render_all(con, panel, entities, player, game_map, fov_map, fov_recompute, message_log, screen_width, screen_height, bar_width, panel_height, panel_y, mouse, colors, game_state): if fov_recompute: for y in range(game_map.height): for x in range(game_map.width): visible = libtcod.map_is_in_fov(fov_map, x, y) wall = game_map.tiles[x][y].block_sight if visible: lighting = 'illuminated' if player.equipment and player.equipment.fov_bonus > 0 else 'shadowed' if wall: libtcod.console_set_char_background(con, x, y, colors.get(f'{lighting}_wall'), libtcod.BKGND_SET) else: libtcod.console_set_char_background(con, x, y, colors.get(f'{lighting}_ground'), libtcod.BKGND_SET) game_map.tiles[x][y].explored = True elif game_map.tiles[x][y].explored: if wall: libtcod.console_set_char_background(con, x, y, colors.get('dark_wall'), libtcod.BKGND_SET) else: libtcod.console_set_char_background(con, x, y, colors.get('dark_ground'), libtcod.BKGND_SET) entities_in_render_order = sorted(entities, key=lambda x: x.render_order.value) # Draw all entities in the list for entity in entities_in_render_order: draw_entity(con, entity, fov_map, game_map) # Cast a spooky shadow under the ghost/possessed creature libtcod.console_set_char_background(con, player.x, player.y, colors.get('dark_ground'), libtcod.BKGND_SET) libtcod.console_set_default_foreground(con, libtcod.white) if player.fighter: libtcod.console_print_ex(con, 1, screen_height - 2, libtcod.BKGND_NONE, libtcod.LEFT, 'HP: {0:02}/{1:02}'.format(player.fighter.hp, player.fighter.max_hp)) libtcod.console_blit(con, 0, 0, screen_width, screen_height, 0, 0, 0) if game_state in (GameStates.SHOW_INVENTORY, GameStates.DROP_INVENTORY): if game_state == GameStates.SHOW_INVENTORY: inventory_title = 'Press the key next to an item to use it, or Esc to cancel.\n' else: inventory_title = 'Press the key next to an item to drop it, or Esc to cancel.\n' inventory_menu(con, inventory_title, player, 50, screen_width, screen_height) elif game_state == GameStates.LEVEL_UP: level_up_menu(con, 'Level up!', player, 40, screen_width, screen_height) elif game_state == GameStates.CHARACTER_SCREEN: character_screen(player, 30, 10, screen_width, screen_height) elif game_state == GameStates.PLAYER_DEAD: death_screen(30, 10, screen_width, screen_height) libtcod.console_set_default_background(panel, libtcod.black) libtcod.console_clear(panel) # Print the game messages, one line at a time y = 1 for message in message_log.messages: libtcod.console_set_default_foreground(panel, message.color) libtcod.console_print_ex(panel, message_log.x, y, libtcod.BKGND_NONE, libtcod.LEFT, message.text) y += 1 if player.fighter: if player.possessed_entity and player.possessed_entity.name: centered_name = player.possessed_entity.name.center(20) else: centered_name = "???".center(20) libtcod.console_set_default_foreground(panel, libtcod.white) libtcod.console_print_ex(panel, 1, 1, libtcod.BKGND_NONE, libtcod.LEFT, centered_name) render_bar(panel, 1, 2, bar_width, 'HP', player.fighter.hp, player.fighter.max_hp, libtcod.light_red, libtcod.darker_red) libtcod.console_print_ex(panel, 1, 3, libtcod.BKGND_NONE, libtcod.LEFT, 'Dungeon level: {0}'.format(game_map.dungeon_level)) libtcod.console_set_default_foreground(panel, libtcod.light_gray) libtcod.console_print_ex(panel, 1, 0, libtcod.BKGND_NONE, libtcod.LEFT, get_names_under_mouse(mouse, entities, fov_map)) libtcod.console_blit(panel, 0, 0, screen_width, panel_height, 0, 0, panel_y)
def main(): """ L'une des deux fonctions principales du jeu, elle est appelée une seule et unique fois : au démarrage du jeu. Elle a la charge de gérer le choix d'affichage des menus et les réactions aux inputs du joueur. Lorsque le joueur quitte un menu pour retourner en jeu, elle appelle la deuxième fonction de ce module : play_game Parametres: ---------- Aucun Renvoi: ------- Aucun """ # Initialise le jeu en commencant par afficher le menu principal constants = get_constants() # The font has 32 chars in a row, and there's a total of 10 rows. Increase the "10" when you add new rows to the sample font file libtcod.console_set_custom_font('textures.png', libtcod.FONT_TYPE_GREYSCALE | libtcod.FONT_LAYOUT_TCOD, 32, 10) load_customfont() libtcod.console_init_root(constants['screen_width'], constants['screen_height'], "Rogue doesn't like", False) con = libtcod.console_new(constants['screen_width'], constants['screen_height']) panel = libtcod.console_new(constants['screen_width'], constants['panel_height']) player = None entities = [] game_map = None message_log = None game_state = None show_main_menu = True show_load_error_message = False show_command_menu = False show_scores = False main_menu_background_image = libtcod.image_load('menu_background.png') play_bg_music = False bg_music = sm.choose_sound(constants.get('sound').get('background_music')) key = libtcod.Key() mouse = libtcod.Mouse() score = (1, 0) while not libtcod.console_is_window_closed(): libtcod.sys_check_for_event(libtcod.EVENT_KEY_PRESS | libtcod.EVENT_MOUSE, key, mouse) # Si le menu principal est affiche : if show_main_menu: main_menu(con, main_menu_background_image, constants['screen_width'], constants['screen_height']) if show_load_error_message: message_box(con, 'Rien a charger', 70, constants['screen_width'], constants['screen_height']) libtcod.console_flush() action = handle_main_menu(key) new_game = action.get('new_game') load_saved_game = action.get('load_game') exit_game = action.get('exit') sound = action.get('sound') command = action.get('command') back_to_game = action.get('back_to_game') scores = action.get('scores') if show_load_error_message and (new_game or load_saved_game or exit_game): show_load_error_message = False # Cree une nouvelle partie elif new_game: if score != (1, 0): save_score(score) player, entities, game_map, message_log, game_state = get_game_variables(constants) game_state = GameStates.PLAYERS_TURN show_main_menu = False # Charge une partie existante, si possible elif load_saved_game: try: player, entities, game_map, message_log, game_state, score = load_game() show_main_menu = False except FileNotFoundError: show_load_error_message = True elif exit_game: if score != (1, 0): save_game(player, entities, game_map, message_log, game_state, score) sm.close_sound() break # Lit ou arrete la musique de fond elif sound: play_bg_music = not play_bg_music bg_music.playpause() elif command: show_command_menu = True show_main_menu = False elif back_to_game and show_main_menu and game_state != GameStates.PLAYER_DEAD: show_main_menu = False elif scores: show_main_menu = False show_scores = True # Affiche le menu des commandes elif show_command_menu: action = handle_main_menu(key) command_menu(con, main_menu_background_image, constants['screen_width'], constants['screen_height']) libtcod.console_flush() back_to_game = action.get('back_to_game') if back_to_game: show_main_menu = True show_command_menu = False libtcod.console_clear(con) # Affiche les trois meilleurs scores et le dernier elif show_scores: action = handle_main_menu(key) scores_menu(con, main_menu_background_image, constants['screen_width'], constants['screen_height']) libtcod.console_flush() back_to_game = action.get('back_to_game') if back_to_game: show_main_menu = True show_scores = False libtcod.console_clear(con) # Lance une partie else: libtcod.console_clear(con) player, entities, game_map, message_log, game_state, bg_music, play_bg_music, score = play_game(player, entities, game_map, message_log, game_state, con, panel, constants, bg_music, play_bg_music, score) if game_state == GameStates.PLAYER_DEAD: show_scores = True else: show_main_menu = True
def on_draw(self, dt): tcod.console_clear(tcod.root_console) self.draw() tcod.console_flush()
def render_all(): global fov_map, color_dark_wall, color_light_wall global color_dark_ground, color_light_ground global fov_recompute if fov_recompute: #recompute FOV if needed (the player moved or something) fov_recompute = False libtcod.map_compute_fov(fov_map, player.x, player.y, TORCH_RADIUS, FOV_LIGHT_WALLS, FOV_ALGO) #go through all tiles, and set their background color according to the FOV for y in range(MAP_HEIGHT): for x in range(MAP_WIDTH): visible = libtcod.map_is_in_fov(fov_map, x, y) wall = map[x][y].block_sight if not visible: #if it's not visible right now, the player can only see it if it's explored if map[x][y].explored: if wall: libtcod.console_set_char_background(con, x, y, color_dark_wall, libtcod.BKGND_SET) else: libtcod.console_set_char_background(con, x, y, color_dark_ground, libtcod.BKGND_SET) else: #it's visible if wall: libtcod.console_set_char_background(con, x, y, color_light_wall, libtcod.BKGND_SET ) else: libtcod.console_set_char_background(con, x, y, color_light_ground, libtcod.BKGND_SET ) #since it's visible, explore it map[x][y].explored = True #draw all objects in the list, except the player. we want it to #always appear over all other objects! so it's drawn later. for object in objects: if object != player: object.draw() player.draw() #blit the contents of "con" to the root console libtcod.console_blit(con, 0, 0, MAP_WIDTH, MAP_HEIGHT, 0, 0, 0) #prepare to render the GUI panel libtcod.console_set_default_background(panel, libtcod.black) libtcod.console_clear(panel) #print the game messages, one line at a time y = 1 for (line, color) in game_msgs: libtcod.console_set_default_foreground(panel, color) libtcod.console_print_ex(panel, MSG_X, y, libtcod.BKGND_NONE, libtcod.LEFT, line) y += 1 #show the player's stats render_bar(1, 1, BAR_WIDTH, 'HP', player.fighter.hp, player.fighter.max_hp, libtcod.light_red, libtcod.darker_red) #display names of objects under the mouse libtcod.console_set_default_foreground(panel, libtcod.light_gray) libtcod.console_print_ex(panel, 1, 0, libtcod.BKGND_NONE, libtcod.LEFT, get_names_under_mouse()) #blit the contents of "panel" to the root console libtcod.console_blit(panel, 0, 0, SCREEN_WIDTH, PANEL_HEIGHT, 0, 0, PANEL_Y)
def update(self, state, results, scene): for result in results: print("Processing result %s" % result) message = result.get('message') stat_heal = result.get('stat_heal') stat_damage = result.get('stat_damage') stat_magic_damage = result.get('stat_magic_damage') stat_paralyzed = result.get('stat_paralyzed') dead_entity = result.get('dead') item_added = result.get('item_added') item_consumed = result.get('consumed') item_dropped = result.get('item_dropped') equip = result.get('equip') boss_dead = result.get('boss_dead') targeting = result.get('targeting') targeting_index = result.get('targeting_index') targeting_cancelled = result.get('targeting_cancelled') targeting_area = result.get('targeting_area') targeting_radius = result.get('radius') exit_game = result.get('exit_game') open_shop = result.get('open_shop') container_consumed = result.get('container_consumed') loot = result.get('loot') next_stage = result.get('next_stage') if stat_heal: state.history.healed += stat_heal if stat_paralyzed: state.history.paralyzed += 1 if stat_magic_damage: state.history.compute_magic_damage(stat_magic_damage) if stat_damage: target = stat_damage.get('target') amount = stat_damage.get('amount') state.history.compute_damage(target, amount) if exit_game: return {'exit_game': True} if message: state.message_log.add_message(message) if dead_entity: if dead_entity == state.player: message, state.game_state = GameAiAct.kill_player( dead_entity) else: state.history.killed_monster(dead_entity.name) message = GameAiAct.kill_monster(dead_entity) state.message_log.add_message(message) if item_added: state.entities.remove(item_added) state.history.compute_loot(item_added) state.game_state = GameStates.ENEMY_TURN if container_consumed: state.entities.remove(container_consumed) state.history.chests_open += 1 state.game_state = GameStates.ENEMY_TURN if loot: message = state.player.purse.add_coins(loot) #state.message_log.add_message(message) if boss_dead: print("Boss dead event!") state.history.bosses_killed += 1 state.entities = state.game_map.next_floor( state.player, state.message_log, CONFIG, component) scene.fov_map = GameScene.init_fov_map(state.game_map) scene.fov_recompute = True tcod.console_clear(scene.owner.con) if item_consumed: state.game_state = GameStates.ENEMY_TURN if open_shop: state.game_state = GameStates.SHOP if equip: equip_results = state.player.equipment.toggle_equip(equip) for equip_results in equip_results: equipped = equip_results.get('equipped') dequipped = equip_results.get('dequipped') if equipped: state.message_log.add_message( Message('Equipped %s' % equipped)) if dequipped: state.message_log.add_message( Message('Dequipped %s' % dequipped)) state.game_state = GameStates.ENEMY_TURN if item_dropped: state.entities.append(item_dropped) state.game_state = GameStates.ENEMY_TURN if targeting: state.previous_game_state = GameStates.PLAYERS_TURN state.game_state = GameStates.TARGETING state.targeting_item = targeting state.message_log.add_message( state.targeting_item.item.targeting_message) if targeting_area and targeting_radius: state.targeting_area = True state.targeting_radius = targeting_radius else: state.targeting_area = False if targeting_index: state.targeting_index = targeting_index if targeting_cancelled: state.game_state = state.previous_game_state state.message_log.add_message(Message('Targeting Cancelled')) if next_stage: return {'next_stage': next_stage} return {}
def render_all(con, panel, entities, player, game_map, fov_map, fov_recompute, message_log, screen_width, screen_height, bar_width, panel_height, panel_y, colors, game_state, current_enemy, player_target): if fov_recompute: for y in range(game_map.height): for x in range(game_map.width): visible = tcod.map_is_in_fov(fov_map, x, y) wall = game_map.tiles[x][y].block_sight if visible: if wall: tcod.console_set_char_background( con, x, y, colors.get('light_wall'), tcod.BKGND_SET) else: tcod.console_set_char_background( con, x, y, colors.get('light_ground'), tcod.BKGND_SET) game_map.tiles[x][y].explored = True elif game_map.tiles[x][y].explored: if wall: tcod.console_set_char_background( con, x, y, colors.get('dark_wall'), tcod.BKGND_SET) else: tcod.console_set_char_background( con, x, y, colors.get('dark_ground'), tcod.BKGND_SET) elif game_state != GameStates.SHOW_INVENTORY: tcod.console_set_char_background(con, x, y, colors.get('black'), tcod.BKGND_SET) tcod.console_put_char(con, x, y, ' ', tcod.BKGND_NONE) entities_in_render_order = sorted(entities, key=lambda x: x.render_order.value) for entity in entities_in_render_order: draw_entity(con, entity, fov_map) tcod.console_set_default_background(panel, tcod.black) tcod.console_clear(panel) y = 1 for message in message_log.messages: tcod.console_set_default_foreground(panel, message.color) tcod.console_print_ex(panel, message_log.x, y, tcod.BKGND_NONE, tcod.LEFT, message.text) y += 1 render_bar(panel, 1, 1, bar_width, 'HP', player.fighter.hp, player.fighter.max_hp, tcod.light_red, tcod.darker_red) if current_enemy: render_bar(con, int(screen_width / 2) - int(bar_width / 2), 1, bar_width, 'HP', player.current_enemy.hp, player.current_enemy.max_hp, tcod.light_red, tcod.darker_red) if game_state in (GameStates.LOOKING, GameStates.TARGETING): tcod.console_set_char_background(con, player_target.x, player_target.y, tcod.light_gray, tcod.BKGND_SET) tcod.console_set_default_foreground(panel, tcod.light_gray) tcod.console_print_ex( panel, 1, 0, tcod.BKGND_NONE, tcod.LEFT, get_names_at_target(entities, fov_map, player_target)) tcod.console_blit(con, 0, 0, screen_width, screen_height, 0, 0, 0) tcod.console_blit(panel, 0, 0, screen_width, panel_height, 0, 0, panel_y) if game_state in (GameStates.SHOW_INVENTORY, GameStates.DROP_INVENTORY): if game_state == GameStates.SHOW_INVENTORY: inventory_title = 'Press the key next to an item to use it, or use Esc to cancel.\n' elif game_state == GameStates.DROP_INVENTORY: inventory_title = 'Press the key next to an item to drop it, or use Esc to cancel.\n' inventory_menu(con, inventory_title, player.inventory, 50, screen_width, screen_height)
def main(): constants = get_constants() libtcod.console_set_custom_font( 'arial10x10.png', libtcod.FONT_TYPE_GRAYSCALE | libtcod.FONT_LAYOUT_TCOD) libtcod.console_init_root(constants['screen_width'], constants['screen_height'], constants['window_title'], False) con = libtcod.console_new(constants['screen_width'], constants['screen_height']) panel = libtcod.console_new(constants['screen_width'], constants['panel_height']) player = None entities = [] game_map = None message_log = None game_state = None show_main_menu = True show_load_error_message = False main_menu_background_image = libtcod.image_load('menu_background1.png') key = libtcod.Key() mouse = libtcod.Mouse() while not libtcod.console_is_window_closed(): libtcod.sys_check_for_event( libtcod.EVENT_KEY_PRESS | libtcod.EVENT_MOUSE, key, mouse) if show_main_menu: main_menu(con, main_menu_background_image, constants['screen_width'], constants['screen_height']) if show_load_error_message: message_box(con, 'No save game to load', 50, constants['screen_width'], constants['screen_height']) libtcod.console_flush() action = handle_main_menu(key) new_game = action.get('new_game') load_saved_game = action.get('load_game') exit_game = action.get('exit') if show_load_error_message and (new_game or load_saved_game or exit_game): show_load_error_message = False elif new_game: player, entities, game_map, message_log, game_state = get_game_variables( constants) game_state = GameStates.PLAYERS_TURN show_main_menu = False elif load_saved_game: try: player, entities, game_map, message_log, game_state = load_game( ) show_main_menu = False except FileNotFoundError: show_load_error_message = True elif exit_game: break else: libtcod.console_clear(con) play_game(player, entities, game_map, message_log, game_state, con, panel, constants) show_main_menu = True player, entities, game_map, message_log, game_state, = get_game_variables( constants)
def render_all(con, panel, entities, player, game_map, fov_map, fov_recompute, message_log, screen_width, screen_height, bar_width, panel_height, panel_y, mouse, colors): # Draw all tiles in game map if fov_recompute: for y in range(game_map.height): for x in range(game_map.width): visible = libtcod.map_is_in_fov(fov_map, x, y) wall = game_map.tiles[x][y].block_sight if visible: if wall: libtcod.console_set_char_background( con, x, y, colors.get('light_wall'), libtcod.BKGND_SET) else: libtcod.console_set_char_background( con, x, y, colors.get('light_ground'), libtcod.BKGND_SET) game_map.tiles[x][y].explored = True elif game_map.tiles[x][y].explored: if wall: libtcod.console_set_char_background( con, x, y, colors.get('dark_wall'), libtcod.BKGND_SET) else: libtcod.console_set_char_background( con, x, y, colors.get('dark_ground'), libtcod.BKGND_SET) entities_in_render_order = sorted(entities, key=lambda x: x.render_order.value) for entity in entities_in_render_order: draw_entity(con, entity, fov_map) libtcod.console_set_default_foreground(con, libtcod.white) libtcod.console_print_ex( con, 1, screen_height - 2, libtcod.BKGND_NONE, libtcod.LEFT, 'HP: {0:02}/{1:02}'.format(player.fighter.hp, player.fighter.max_hp)) libtcod.console_blit(con, 0, 0, screen_width, screen_height, 0, 0, 0) libtcod.console_set_default_background(panel, libtcod.black) libtcod.console_clear(panel) # print game messages one line at a time y = 1 for message in message_log.messages: libtcod.console_set_default_foreground(panel, message.color) libtcod.console_print_ex(panel, message_log.x, y, libtcod.BKGND_NONE, libtcod.LEFT, message.text) y += 1 render_bar(panel, 1, 1, bar_width, 'HP', player.fighter.hp, player.fighter.max_hp, libtcod.light_red, libtcod.darker_red) libtcod.console_set_default_foreground(panel, libtcod.light_grey) libtcod.console_print_ex(panel, 1, 0, libtcod.BKGND_NONE, libtcod.LEFT, get_names_under_mouse(mouse, entities, fov_map)) libtcod.console_blit(panel, 0, 0, screen_width, panel_height, 0, 0, panel_y)
def update_render_text(self): libtcod.console_clear(self.console) libtcod.console_print_ex(self.console, 0, 0, libtcod.BKGND_NONE, libtcod.LEFT, self.text) self.blit_console()
def main(): constants = get_constants() libtcod.console_set_custom_font( 'TiledFont.png', libtcod.FONT_TYPE_GREYSCALE | libtcod.FONT_LAYOUT_TCOD, 32, 10) libtcod.console_init_root(constants['screen_width'], constants['screen_height'], constants['window_title'], False) con = libtcod.console_new(constants['screen_width'], constants['screen_height']) panel = libtcod.console_new(constants['screen_width'], constants['panel_height']) player = None entities = [] game_map = None message_log = None game_state = None show_main_menu = True show_character_screen = False start_game = None show_load_error_message = False main_menu_background_image = libtcod.image_load('menu_background.png') key = libtcod.Key() mouse = libtcod.Mouse() while not libtcod.console_is_window_closed(): libtcod.sys_check_for_event( libtcod.EVENT_KEY_PRESS | libtcod.EVENT_MOUSE, key, mouse) if show_main_menu: main_menu(con, main_menu_background_image, constants['screen_width'], constants['screen_height']) if show_load_error_message: message_box(con, 'No save game to load', 50, constants['screen_width'], constants['screen_height']) libtcod.console_flush() action = handle_main_menu(key) new_game = action.get('new_game') load_saved_game = action.get('load_game') exit_game = action.get('exit') choose_fighter = action.get('choose_fighter') if show_load_error_message and (new_game or load_saved_game or exit_game): show_load_error_message = False elif new_game: player, entities, game_map, message_log, game_state = get_game_variables( constants, 'barbarian') game_state = GameStates.PLAYER_TURN show_main_menu = False start_game = True elif load_saved_game: try: player, entities, game_map, message_log, game_state = load_game( ) show_main_menu = False start_game = True except FileNotFoundError: show_load_error_message = True elif choose_fighter: show_main_menu = False #show_character_screen = True new_character_screen(con, main_menu_background_image, constants['screen_width'], constants['screen_height']) libtcod.console_flush() '''TODO: Задать переменную, отвечающую за то, что открыто ли окно choose_fighter или нет''' action_character_menu = handle_new_character_menu_keys(key) warrior = 'warrior' thief = 'thief' barbarian = 'barbarian' exit_character_menu = 'exit' if action_character_menu.get('warrior') == warrior: player, entities, game_map, message_log, game_state = get_game_variables( constants, warrior) game_state = GameStates.PLAYER_TURN #show_character_screen = False #show_main_menu = False #start_game = True #start_game = True choose_fighter = False elif action_character_menu.get('thief') == thief: player, entities, game_map, message_log, game_state = get_game_variables( constants, thief) #game_state = GameStates.PLAYER_TURN #show_character_screen = False choose_fighter = False elif action_character_menu.get('barbarian') == barbarian: player, entities, game_map, message_log, game_state = get_game_variables( constants, barbarian) game_state = GameStates.PLAYER_TURN #show_character_screen = False elif action_character_menu.get('exit') == exit_character_menu: show_character_screen = False show_main_menu = True main_menu(con, main_menu_background_image, constants['screen_width'], constants['screen_height']) libtcod.console_flush() show_character_screen = False elif choose_fighter == False: start_game = True game_state.PLAYER_TURN elif exit_game: break elif start_game == True: libtcod.console_clear(con) play_game(player, entities, game_map, message_log, game_state, con, panel, constants) show_main_menu = True
def render_all(con, panel, entities, player, game_map, fov_map, fov_recompute, message_log, screen_width, screen_height, bar_width, panel_height, panel_y, mouse, colors, game_state): if fov_recompute: for y in range(game_map.height): for x in range(game_map.width): visible = fov_map.fov[y][x] wall = game_map.tiles[x][y].block_sight if visible: if wall: libtcod.console_set_char_background( con, x, y, colors.get("light_wall"), libtcod.BKGND_SET) else: libtcod.console_set_char_background( con, x, y, colors.get("light_ground"), libtcod.BKGND_SET) game_map.tiles[x][y].explored = True elif game_map.tiles[x][y].explored: if wall: libtcod.console_set_char_background( con, x, y, colors.get("dark_wall"), libtcod.BKGND_SET) else: libtcod.console_set_char_background( con, x, y, colors.get("dark_ground"), libtcod.BKGND_SET) entities_in_render_order = sorted(entities, key=lambda x: x.render_order.value) for entity in entities_in_render_order: if fov_map.fov[entity.y][entity.x] or ( entity.stairs and game_map.tiles[entity.x][entity.y].explored): draw_entity(con, entity) libtcod.console_set_default_background(panel, libtcod.black) libtcod.console_clear(panel) render_bar(panel, 1, 1, bar_width, "HP", player.fighter.hp, player.fighter.max_hp, libtcod.light_red, libtcod.darker_red) libtcod.console_print_ex( panel, 1, 3, libtcod.BKGND_NONE, libtcod.LEFT, "Dungeon level: {}".format(game_map.dungeon_level)) libtcod.console_set_default_foreground(panel, libtcod.light_gray) libtcod.console_print_ex(panel, 1, 0, libtcod.BKGND_NONE, libtcod.LEFT, get_names_under_mouse(mouse, entities, fov_map)) y = 1 for message in message_log.messages: libtcod.console_set_default_foreground(panel, message.color) libtcod.console_print_ex(panel, message_log.x, y, libtcod.BKGND_NONE, libtcod.LEFT, message.text) y += 1 libtcod.console_blit(con, 0, 0, screen_width, screen_height, 0, 0, 0) libtcod.console_blit(panel, 0, 0, screen_width, panel_height, 0, 0, panel_y) inventory_title = None if game_state == GameStates.SHOW_INVENTORY: inventory_title = "Press the key next to an item to use it, or Esc to cancel.\n" elif game_state == GameStates.DROP_INVENTORY: inventory_title = "Press the key next to an item to drop it, or Esc to cancel.\n" if inventory_title != None: inventory_menu(con, inventory_title, player, player.inventory, 50, screen_width, screen_height) if game_state == GameStates.LEVEL_UP: level_up_menu(con, "Level up! Choose a stat to raise:", player, 40, screen_width, screen_height) if game_state == GameStates.CHARACTER_SCREEN: character_screen(player, 30, 10, screen_width, screen_height)
def clear(self): tcod.console_clear(self._c)
def render_clean(self, console): if not self.render_next: return tcod.console_clear(self.console) self.render_next = False
def play_game(player, entities, game_map, message_log, game_state, con, panel, constants): fov_recompute = True fov_map = initialize_fov(game_map) key = libtcod.Key() mouse = libtcod.Mouse() game_state = GameStates.PLAYERS_TURN previous_game_state = game_state targeting_item = None # game loop while not libtcod.console_is_window_closed(): # captures user input - will update the key and mouse variables with what the user inputs libtcod.sys_check_for_event( libtcod.EVENT_KEY_PRESS | libtcod.EVENT_MOUSE, key, mouse) if fov_recompute: recompute_fov(fov_map, player.x, player.y, constants['fov_radius'], constants['fov_light_walls'], constants['fov_algorithm']) # draw the entities and blit the changes to the screen - only render the item inventory when the game state is in the inventory state render_all(con, panel, entities, player, game_map, fov_map, fov_recompute, message_log, constants['screen_width'], constants['screen_height'], constants['bar_width'], constants['panel_height'], constants['panel_y'], mouse, constants['colors'], game_state) fov_recompute = False # present everything on the screen libtcod.console_flush() # clear entities after drawing to screen - this makes it so that when entities move, they do not leave a trail behind clear_all(con, entities) # gives a way to gracefully exit program by hitting the ESC key # gets any keyboard input to the program and stores in the key variable action = handle_keys(key, game_state) mouse_action = handle_mouse(mouse) move = action.get('move') wait = action.get('wait') pickup = action.get('pickup') show_inventory = action.get('show_inventory') drop_inventory = action.get('drop_inventory') inventory_index = action.get('inventory_index') take_stairs = action.get('take_stairs') level_up = action.get('level_up') show_character_screen = action.get('show_character_screen') exit = action.get('exit') fullscreen = action.get('fullscreen') left_click = mouse_action.get('left_click') right_click = mouse_action.get('right_click') player_turn_results = [] # move the player only on the players turn if move and game_state == GameStates.PLAYERS_TURN: dx, dy = move destination_x = player.x + dx destination_y = player.y + dy # check if there is something at the destination that would block the player - if not, move the player there if not game_map.is_blocked(destination_x, destination_y): target = get_blocking_entities_at_location( entities, destination_x, destination_y) if target: attack_results = player.fighter.attack(target) player_turn_results.extend(attack_results) else: player.move(dx, dy) fov_recompute = True # change to enemy's turn after player's move game_state = GameStates.ENEMY_TURN elif wait: game_state = GameStates.ENEMY_TURN # if the player did not move and performed the pickup action by pressing the key 'g'... elif pickup and game_state == GameStates.PLAYERS_TURN: # loop through each entity on the map, check if it is an item and occupies the same space as the player for entity in entities: # if the entity is an item and in the same position as the player if entity.item and entity.x == player.x and entity.y == player.y: # add the item to the inventory and append the results to player_turn_results pickup_results = player.inventory.add_item(entity) player_turn_results.extend(pickup_results) break # makes it so the player only picks up one item at a time else: message_log.add_message( Message('There is nothing here to pick up.', libtcod.yellow)) if show_inventory: previous_game_state = game_state game_state = GameStates.SHOW_INVENTORY if drop_inventory: previous_game_state = game_state game_state = GameStates.DROP_INVENTORY # take the index selected, use the item selected if inventory_index is not None and previous_game_state != GameStates.PLAYER_DEAD and inventory_index < len( player.inventory.items): item = player.inventory.items[inventory_index] if game_state == GameStates.SHOW_INVENTORY: player_turn_results.extend( player.inventory.use(item, entities=entities, fov_map=fov_map)) elif game_state == GameStates.DROP_INVENTORY: player_turn_results.extend(player.inventory.drop_item(item)) if take_stairs and game_state == GameStates.PLAYERS_TURN: for entity in entities: if entity.stairs and entity.x == player.x and entity.y == player.y: entities = game_map.next_floor(player, message_log, constants) fov_map = initialize_fov(game_map) fov_recompute = True libtcod.console_clear(con) break else: message_log.add_message( Message('There are no stairs here.', libtcod.yellow)) if level_up: if level_up == 'hp': player.fighter.max_hp += 20 player.fighter.hp += 20 elif level_up == 'str': player.fighter.power += 1 elif level_up == 'def': player.fighter.defense += 1 game_state = previous_game_state if show_character_screen: previous_game_state = game_state game_state = GameStates.CHARACTER_SCREEN if game_state == GameStates.TARGETING: if left_click: target_x, target_y = left_click item_use_results = player.inventory.use(targeting_item, entities=entities, fov_map=fov_map, target_x=target_x, target_y=target_y) player_turn_results.extend(item_use_results) elif right_click: player_turn_results.append({'targeting_cancelled': True}) # checks if the key pressed was the Esc key - if it was, then exit the loop if exit: if game_state in (GameStates.SHOW_INVENTORY, GameStates.DROP_INVENTORY, GameStates.CHARACTER_SCREEN): game_state = previous_game_state elif game_state == GameStates.TARGETING: player_turn_results.append({'targeting_cancelled': True}) else: save_game(player, entities, game_map, message_log, game_state) return True if fullscreen: libtcod.console_set_fullscreen( (not libtcod.console_is_fullscreen())) for player_turn_result in player_turn_results: message = player_turn_result.get('message') dead_entity = player_turn_result.get('dead') item_added = player_turn_result.get('item_added') item_consumed = player_turn_result.get('consumed') item_dropped = player_turn_result.get('item_dropped') targeting = player_turn_result.get('targeting') targeting_cancelled = player_turn_result.get('targeting_cancelled') xp = player_turn_result.get('xp') if message: message_log.add_message(message) if dead_entity: if dead_entity == player: message, game_state = kill_player(dead_entity) else: message = kill_monster(dead_entity) message_log.add_message(message) if item_added: entities.remove(item_added) game_state = GameStates.ENEMY_TURN if item_dropped: entities.append(item_dropped) game_state = GameStates.ENEMY_TURN if item_consumed: game_state = GameStates.ENEMY_TURN if targeting: previous_game_state = GameStates.PLAYERS_TURN game_state = GameStates.TARGETING targeting_item = targeting message_log.add_message(targeting_item.item.targeting_message) if targeting_cancelled: game_state = previous_game_state message_log.add_message(Message('Targeting cancelled')) if xp: leveled_up = player.level.add_xp(xp) message_log.add_message( Message('You gain {0} experience points.'.format(xp))) if leveled_up: message_log.add_message( Message( 'Your battle skills grow stronger! You reached level {0}' .format(player.level.current_level) + '!', libtcod.yellow)) previous_game_state = game_state game_state = GameStates.LEVEL_UP if game_state == GameStates.ENEMY_TURN: for entity in entities: if entity.ai: enemy_turn_results = entity.ai.take_turn( player, fov_map, game_map, entities) for enemy_turn_result in enemy_turn_results: message = enemy_turn_result.get('message') dead_entity = enemy_turn_result.get('dead') if message: message_log.add_message(message) if dead_entity: if dead_entity == player: message, game_state = kill_player(dead_entity) else: message = kill_monster(dead_entity) message_log.add_message(message) if game_state == GameStates.PLAYER_DEAD: break if game_state == GameStates.PLAYER_DEAD: break # note that this is a for-else statement; without a break statement, this else will always happen else: game_state = GameStates.PLAYERS_TURN
def play_game(player, entities, game_map, message_log, game_state, con, panel, configs): fov_recompute = True fov_map = initialize_fov(game_map) key = tcod.Key() mouse = tcod.Mouse() previous_game_state = game_state targeting_item = None while not tcod.console_is_window_closed(): tcod.sys_check_for_event(tcod.EVENT_KEY_PRESS | tcod.EVENT_MOUSE, key, mouse) if fov_recompute: recompute_fov(fov_map, player.x, player.y, configs["fov_radius"], configs["fov_light_walls"], configs["fov_algorithm"]) render_all( con, panel, entities, player, game_map, fov_map, fov_recompute, message_log, configs["screen_width"], configs["screen_height"], configs["bar_width"], configs["panel_height"], configs["panel_y"], mouse, configs["colors"], game_state, ) fov_recompute = False tcod.console_flush() clear_all(con, entities) action = handle_keys(key, game_state) mouse_action = handle_mouse(mouse) move = action.get("move") wait = action.get("wait") pickup = action.get("pickup") show_inventory = action.get("show_inventory") drop_inventory = action.get("drop_inventory") inventory_index = action.get("inventory_index") take_stairs = action.get("take_stairs") level_up = action.get("level_up") show_character_screen = action.get("show_character_screen") exit = action.get("exit") fullscreen = action.get("fullscreen") left_click = mouse_action.get("left_click") right_click = mouse_action.get("right_click") player_turn_results = [] if move and game_state == GameState.PLAYER_TURN: dx, dy = move destination_x = player.x + dx destination_y = player.y + dy if not game_map.is_blocked(destination_x, destination_y): target = get_blocking_entities_at_location( entities, destination_x, destination_y) if target: attack_results = player.fighter.attack(target) player_turn_results.extend(attack_results) else: player.move(dx, dy) fov_recompute = True game_state = GameState.ENEMY_TURN elif wait: game_state = GameState.ENEMY_TURN elif pickup and game_state == GameState.PLAYER_TURN: for entity in entities: if entity.item and entity.x == player.x and entity.y == player.y: pickup_results = player.inventory.add_item(entity) player_turn_results.extend(pickup_results) break else: message_log.add_message( Message("There is nothing here to pick up.", tcod.yellow)) if show_inventory: previous_game_state = game_state game_state = GameState.SHOW_INVENTORY if drop_inventory: previous_game_state = game_state game_state = GameState.DROP_INVENTORY if (inventory_index is not None and previous_game_state != GameState.PLAYER_DEAD and inventory_index < len(player.inventory.items)): item = player.inventory.items[inventory_index] if game_state == GameState.SHOW_INVENTORY: player_turn_results.extend( player.inventory.use(item, entities=entities, fov_map=fov_map)) elif game_state == GameState.DROP_INVENTORY: player_turn_results.extend(player.inventory.drop_item(item)) if take_stairs and game_state == GameState.PLAYER_TURN: for entity in entities: if entity.stairs and entity.x == player.x and entity.y == player.y: entities = game_map.next_floor(player, message_log, configs) fov_map = initialize_fov(game_map) fov_recompute = True tcod.console_clear(con) break else: message_log.add_message( Message("There are no stairs here.", tcod.yellow)) if level_up: if level_up == "hp": player.fighter.base_max_hp += 20 player.fighter.hp += 20 elif level_up == "str": player.fighter.base_power += 1 elif level_up == "def": player.fighter.base_defense += 1 game_state = previous_game_state if show_character_screen: previous_game_state = game_state game_state = GameState.CHARACTER_SCREEN if game_state == GameState.TARGETING: if left_click: target_x, target_y = left_click item_use_results = player.inventory.use(targeting_item, entities=entities, fov_map=fov_map, target_x=target_x, target_y=target_y) player_turn_results.extend(item_use_results) elif right_click: player_turn_results.append({"targeting_cancelled": True}) if exit: if game_state in (GameState.SHOW_INVENTORY, GameState.DROP_INVENTORY, GameState.CHARACTER_SCREEN): game_state = previous_game_state elif game_state == GameState.TARGETING: player_turn_results.append({"targeting_cancelled": True}) else: save_game(player, entities, game_map, message_log, game_state) return True if fullscreen: tcod.console_set_fullscreen(not tcod.console_is_fullscreen()) for result in player_turn_results: message = result.get("message") dead_entity = result.get("dead") item_added = result.get("item_added") item_consumed = result.get("consumed") item_dropped = result.get("item_dropped") equip = result.get("equip") targeting = result.get("targeting") targeting_cancelled = result.get("targeting_cancelled") xp = result.get("xp") if message: message_log.add_message(message) if targeting_cancelled: game_state = previous_game_state message_log.add_message(Message("Targeting cancelled")) if dead_entity: if dead_entity == player: message, game_state = kill_player(dead_entity) else: message = kill_monster(dead_entity) message_log.add_message(message) if item_added: entities.remove(item_added) game_state = GameState.ENEMY_TURN if item_consumed: game_state = GameState.ENEMY_TURN if item_dropped: entities.append(item_dropped) game_state = GameState.ENEMY_TURN if equip: equip_results = player.equipment.toggle_equip(equip) for equip_results in equip_results: equipped = equip_results.get("equipped") dequipped = equip_results.get("dequipped") if equipped: message_log.add_message( Message(f"You equipped the {equipped.name}.")) if dequipped: message_log.add_message( Message(f"You dequipped the {dequipped.name}.")) game_state - GameState.ENEMY_TURN if targeting: previous_game_state = GameState.PLAYER_TURN game_state = GameState.TARGETING targeting_item = targeting message_log.add_message(targeting_item.item.targeting_message) if xp: leveled_up = player.level.add_xp(xp) message_log.add_message( Message(f"You gain {xp} experience points.")) if leveled_up: message_log.add_message( Message( f"Your battle skills grow strong! You reached level {player.level.current_level}!", tcod.yellow, )) previous_game_state = game_state game_state = GameState.LEVEL_UP if game_state == GameState.ENEMY_TURN: for entity in entities: if entity.ai: enemy_turn_results = entity.ai.take_turn( player, fov_map, game_map, entities) for result in enemy_turn_results: message = result.get("message") dead_entity = result.get("dead") if message: message_log.add_message(message) if dead_entity: if dead_entity == player: message, game_state = kill_player(dead_entity) else: message = kill_monster(dead_entity) message_log.add_message(message) if game_state == GameState.PLAYER_DEAD: break if game_state == GameState.PLAYER_DEAD: break else: game_state = GameState.PLAYER_TURN
def render_all(con, panel, entities, player, game_map, fov_map, fov_recompute, message_log, screen_width, screen_height, bar_width, panel_height, panel_y, mouse, colors, game_state): # Draw all the tiles in the game map if fov_recompute: for y in range(game_map.height): for x in range(game_map.width): visible = libtcod.map_is_in_fov(fov_map, x, y) wall = game_map.tiles[x][y].block_sight if visible: if wall: libtcod.console_set_char_background( con, x, y, colors.get('light_wall'), libtcod.BKGND_SET) else: libtcod.console_set_char_background( con, x, y, colors.get('light_ground'), libtcod.BKGND_SET) game_map.tiles[x][y].explored = True elif game_map.tiles[x][y].explored: if wall: libtcod.console_set_char_background( con, x, y, colors.get('dark_wall'), libtcod.BKGND_SET) else: libtcod.console_set_char_background( con, x, y, colors.get('dark_ground'), libtcod.BKGND_SET) entities_in_render_order = sorted(entities, key=lambda x: x.render_order.value) for entity in entities_in_render_order: draw_entity(con, entity, fov_map) libtcod.console_blit(con, 0, 0, screen_width, screen_height, 0, 0, 0) libtcod.console_set_default_background(panel, libtcod.black) libtcod.console_clear(panel) # Print the game messages, one line at a time y = 1 for message in message_log.messages: libtcod.console_set_default_foreground(panel, message.color) libtcod.console_print_ex(panel, message_log.x, y, libtcod.BKGND_NONE, libtcod.LEFT, message.text) y += 1 render_bar(panel, 1, 1, bar_width, 'HP', player.fighter.hp, player.fighter.max_hp, libtcod.light_red, libtcod.darker_red) libtcod.console_set_default_foreground(panel, libtcod.light_gray) libtcod.console_print_ex(panel, 1, 0, libtcod.BKGND_NONE, libtcod.LEFT, get_names_under_mouse(mouse, entities, fov_map)) libtcod.console_blit(panel, 0, 0, screen_width, panel_height, 0, 0, panel_y) if game_state == GameStates.SHOW_INVENTORY: inventory_menu( con, 'Press the key next to an item to use it, or Esc to cancel.\n', player.inventory, 50, screen_width, screen_height)
def main(): configs = get_configs() tcod.console_set_custom_font( "assets/fonts/arial10x10.png", tcod.FONT_TYPE_GREYSCALE | tcod.FONT_LAYOUT_TCOD) tcod.console_init_root(configs["screen_width"], configs["screen_height"], configs["window_title"], False) con = tcod.console_new(configs["screen_width"], configs["screen_height"]) panel = tcod.console_new(configs["screen_width"], configs["screen_height"]) player = None entities = [] game_map = None message_log = None game_state = None show_main_menu = True show_load_error_message = False main_menu_background_image = tcod.image_load( "assets/images/menu_background.png") key = tcod.Key() mouse = tcod.Mouse() while not tcod.console_is_window_closed(): tcod.sys_check_for_event(tcod.EVENT_KEY_PRESS | tcod.EVENT_MOUSE, key, mouse) if show_main_menu: main_menu(con, main_menu_background_image, configs["screen_width"], configs["screen_height"]) if show_load_error_message: message_box(con, "No save game to load", 50, configs["screen_width"], configs["screen_height"]) tcod.console_flush() action = handle_main_menu(key) new_game = action.get("new_game") load_saved_game = action.get("load_game") exit_game = action.get("exit") if show_load_error_message and (new_game or load_saved_game or exit_game): show_load_error_message = False elif new_game: player, entities, game_map, message_log, game_state = get_game_variables( configs) show_main_menu = False elif load_saved_game: try: player, entities, game_map, message_log, game_state = load_game( ) show_main_menu = False except FileNotFoundError: show_load_error_message = True elif exit_game: break else: tcod.console_clear(con) play_game(player, entities, game_map, message_log, game_state, con, panel, configs) show_main_menu = True
def render_all(drawing_con, panel, entities, player, game_map, fov_map, fov_recompute, message_log, screen_width, screen_height, bar_width, panel_height, panel_y, mouse, colors, game_state): if fov_recompute: for y in range(game_map.height): for x in range(game_map.width): visible = libtcod.map_is_in_fov(fov_map, x, y) wall = game_map.tiles[x][y].block_sight if visible: if wall: libtcod.console_set_char_background( drawing_con, x, y, colors.get('light_wall'), libtcod.BKGND_SET) else: libtcod.console_set_char_background( drawing_con, x, y, colors.get('light_ground'), libtcod.BKGND_SET) game_map.tiles[x][y].explored = True elif game_map.tiles[x][y].explored: if wall: libtcod.console_set_char_background( drawing_con, x, y, colors.get('dark_wall'), libtcod.BKGND_SET) else: libtcod.console_set_char_background( drawing_con, x, y, colors.get('dark_ground'), libtcod.BKGND_SET) entities_in_render_order = sorted(entities, key=lambda x: x.render_order.value) # Draw all entities in the list for entity in entities_in_render_order: draw_entity(drawing_con, entity, fov_map, game_map) libtcod.console_blit(drawing_con, 0, 0, screen_width, screen_height, 0, 0, 0) libtcod.console_set_default_background(panel, libtcod.black) libtcod.console_clear(panel) # Print the game messages, one line at a time y = 1 for message in message_log.messages: libtcod.console_set_default_foreground(panel, message.color) libtcod.console_print_ex(panel, message_log.x, y, libtcod.BKGND_NONE, libtcod.LEFT, message.text) y += 1 render_bar(panel, 1, 1, bar_width, 'HP', player.fighter.hp, player.fighter.max_hp, libtcod.darker_green, libtcod.darker_red) libtcod.console_print_ex( panel, 1, 3, libtcod.BKGND_NONE, libtcod.LEFT, 'Dungeon level: {0}'.format(game_map.dungeon_level)) libtcod.console_set_default_foreground(panel, libtcod.light_gray) libtcod.console_print_ex(panel, 1, 0, libtcod.BKGND_NONE, libtcod.LEFT, get_names_under_mouse(mouse, entities, fov_map)) libtcod.console_blit(panel, 0, 0, screen_width, panel_height, 0, 0, panel_y) if game_state in (GameStates.SHOW_INVENTORY, GameStates.DROP_INVENTORY): if game_state == GameStates.SHOW_INVENTORY: inventory_title = 'Press the key next to an item to use it, or Esc to cancel.\n' else: inventory_title = 'Press the key next to an item to drop it, or Esc to cancel.\n' inventory_menu(drawing_con, inventory_title, player.inventory, 50, screen_width, screen_height) elif game_state == GameStates.LEVEL_UP: level_up_menu(drawing_con, 'Level up! Choose a stat to raise:', player, 40, screen_width, screen_height) elif game_state == GameStates.CHARACTER_SCREEN: character_screen(player, 30, 10, screen_width, screen_height)
def play_game(player, entities, game_map, message_log, game_state, con, panel, constants): # Intialize FOV map. fov_recompute = True # Recompute FOV after the player moves fov_map = initialize_fov(game_map) target_fov_map = initialize_fov(game_map) fov_map_no_walls = initialize_fov(game_map) # Capture keyboard and mouse input key = libtcod.Key() mouse = libtcod.Mouse() game_state = GameStates.PLAYERS_TURN previous_game_state = game_state # Store the item that the player used to enter targeting mode (ie lightning scroll). This is so that we know what item we need to remove from inventory etc. targeting_item = None cursor_radius = 1 # For showing object descriptions description_recompute = True description_list = [] description_index = 0 prev_mouse_y = None prev_mouse_x = None # Start music mixer.init() mixer.music.load(os.path.join(definitions.ROOT_DIR, 'data', 'music', 'bgm2.mp3')) #mixer.music.play(loops=-1) #Our main loop while not libtcod.console_is_window_closed(): # Check for input libtcod.sys_check_for_event(libtcod.EVENT_KEY_PRESS | libtcod.EVENT_MOUSE, key, mouse) for animator in Animator.animators: animator.update() if Animator.blocking > 0: if not game_state == GameStates.BLOCKING_ANIMATION: previous_game_state = game_state game_state = GameStates.BLOCKING_ANIMATION if Animator.blocking == 0 and game_state == GameStates.BLOCKING_ANIMATION: game_state = previous_game_state # Recompute FOV if fov_recompute: recompute_fov(fov_map, player.x, player.y, constants['fov_radius'], constants['fov_light_walls'], constants['fov_algorithm']) recompute_fov(fov_map_no_walls, player.x, player.y, constants['fov_radius'], light_walls=False, algorithm=constants['fov_algorithm']) # Show object descriptions if description_recompute == True: for entity in entities: if (prev_mouse_x != mouse.cx) or (prev_mouse_y != mouse.cy): description_list = [] description_index = 0 if entity.x == mouse.cx and entity.y == mouse.cy: description_list.append(entity) prev_mouse_x = mouse.cx prev_mouse_y = mouse.cy if len(description_list) > 0: description_recompute = False # We need to check to see if the mouse position changed and then clear our description list if it did, otherwise it will keep growing if (prev_mouse_x != mouse.cx) or (prev_mouse_y != mouse.cy): description_list = [] description_index = 0 description_recompute = True if mouse.lbutton_pressed: description_index += 1 if description_index > (len(description_list) - 1): description_index = 0 # Draw our scene render_all(con, panel, mouse, entities, player, game_map, fov_map, fov_recompute, message_log, constants['screen_width'], constants['screen_height'], constants['bar_width'], constants['panel_height'], constants['panel_y'], constants['colors'], game_state, description_list, description_index, cursor_radius, target_fov_map, fov_map_no_walls) fov_recompute = False libtcod.console_flush() # Clear our 'drawing consoles' so we dont leave a trail on the main console screen clear_all(con, entities) # Store input results action = handle_keys(key, game_state) mouse_action = handle_mouse(mouse) key = libtcod.Key() mouse = libtcod.Mouse() move = action.get('move') pickup = action.get('pickup') show_inventory = action.get('show_inventory') drop_inventory = action.get('drop_inventory') inventory_index = action.get('inventory_index') take_stairs = action.get('take_stairs') level_up = action.get('level_up') show_character_screen = action.get('show_character_screen') ability_1 = action.get('ability_1') exit = action.get('exit') fullscreen = action.get('fullscreen') left_click = mouse_action.get('left_click') right_click = mouse_action.get('right_click') #Instatiate our message queue for the players turn player_turn_results = [] # Player Actions # Move if move and game_state == GameStates.PLAYERS_TURN: if not move == 'wait': dx, dy = move destination_x = player.x + dx destination_y = player.y + dy # Check to see if the location we want to move to is blocked by a wall or inhabited by a creature if not game_map.is_blocked(destination_x, destination_y): target = get_blocking_entities_at_location(entities, destination_x, destination_y) # If blocked by a creature, attack if target: attack_results = player.fighter.attack(target) player_turn_results.extend(attack_results) # Otherwise, move. else: player.move(dx, dy) fov_recompute = True game_state = GameStates.ENEMY_TURN else: game_state = GameStates.ENEMY_TURN elif pickup and game_state == GameStates.PLAYERS_TURN: for entity in entities: if entity.item and entity.x == player.x and entity.y == player.y: pickup_results = player.inventory.add_item(entity) player_turn_results.extend(pickup_results) break else: message_log.add_message(Message('There is nothing here to pick up.', libtcod.yellow)) #Ability complete checks: for ability in player.abilities: if player.animator.caller == ability and player.animator.complete: player_turn_results.extend(ability.use(complete=True)) player.animator.caller = None player.animator.complete = None if ability_1: player_turn_results.extend(player.abilities[0].use()) if show_inventory: if game_state != GameStates.SHOW_INVENTORY: previous_game_state = game_state player.inventory.sort_items() game_state = GameStates.SHOW_INVENTORY if drop_inventory: if game_state != GameStates.DROP_INVENTORY: previous_game_state = game_state game_state = GameStates.DROP_INVENTORY #Use or drop item in inventory if inventory_index is not None and previous_game_state != GameStates.PLAYER_DEAD and inventory_index < len(player.inventory.items): item = player.inventory.items[inventory_index] if game_state == GameStates.SHOW_INVENTORY: player_turn_results.extend(player.inventory.use(item, entities=entities, fov_map=fov_map)) elif game_state == GameStates.DROP_INVENTORY: player_turn_results.extend(player.inventory.drop_item(item)) if take_stairs and game_state == GameStates.PLAYERS_TURN: for entity in entities: if entity.stairs and entity.x == player.x and entity.y == player.y: entities = game_map.next_floor(player, message_log, constants) fov_map = initialize_fov(game_map) target_fov_map = initialize_fov(game_map) fov_map_no_walls = initialize_fov(game_map) fov_recompute = True libtcod.console_clear(con) break else: message_log.add_message(Message('There are no stairs here.', libtcod.yellow)) if level_up: if level_up == 'hp': player.fighter.con += 1 message_log.add_message(Message('Your Constitution has increased by 1!', libtcod.yellow)) elif level_up == 'str': player.fighter.base_power += 1 message_log.add_message(Message('Your Strength has increased by 1!', libtcod.yellow)) elif level_up == 'def': player.fighter.base_defense += 1 message_log.add_message(Message('Your Defense has increased by 1!', libtcod.yellow)) hp_increase = randint(player.fighter.hitdie[0], player.fighter.hitdie[1]) + int((player.fighter.con - 10) / 2) player.fighter.base_max_hp += hp_increase player.fighter.hp += hp_increase message_log.add_message(Message('Your HP has increased by {0}'.format(hp_increase) + '!', libtcod.yellow)) game_state = previous_game_state if show_character_screen: if not game_state == GameStates.CHARACTER_SCREEN: previous_game_state = game_state game_state = GameStates.CHARACTER_SCREEN if game_state == GameStates.TARGETING: if hasattr(targeting_item, 'item'): cursor_radius = targeting_item.item.function_kwargs.get('radius') else: cursor_radius = targeting_item.function_kwargs.get('radius') if left_click: target_x, target_y = left_click if hasattr(targeting_item, 'item'): item_use_results = player.inventory.use(targeting_item, entities=entities, fov_map=fov_map, target_fov_map=target_fov_map,target_x=target_x, target_y=target_y) else: item_use_results = targeting_item.use(entities=entities, fov_map=fov_map, target_fov_map=target_fov_map,target_x=target_x, target_y=target_y) player_turn_results.extend(item_use_results) cursor_radius = 1 elif right_click: player_turn_results.append({'targeting_cancelled': True}) cursor_radius = 1 if exit: if game_state in (GameStates.SHOW_INVENTORY, GameStates.DROP_INVENTORY, GameStates.CHARACTER_SCREEN): game_state = previous_game_state elif game_state == GameStates.TARGETING: player_turn_results.append({'targeting_cancelled': True}) cursor_radius = 1 else: save_game(player, entities, game_map, message_log, game_state) return True if fullscreen: libtcod.console_set_fullscreen(not libtcod.console_is_fullscreen()) # Check player message queue and react accordingly for player_turn_result in player_turn_results: message = player_turn_result.get('message') dead_entity = player_turn_result.get('dead') item_added = player_turn_result.get('item_added') item_consumed = player_turn_result.get('consumed') item_dropped = player_turn_result.get('item_dropped') equip = player_turn_result.get('equip') targeting = player_turn_result.get('targeting') targeting_cancelled = player_turn_result.get('targeting_cancelled') ability_used = player_turn_result.get("ability_used") xp = player_turn_result.get('xp') if message: message_log.add_message(message) if targeting_cancelled: game_state = previous_game_state message_log.add_message(Message('Targeting cancelled')) if dead_entity: if dead_entity == player: message, game_state = kill_player(dead_entity) else: message = kill_monster(dead_entity) message_log.add_message(message) if item_added: entities.remove(item_added) game_state = GameStates.ENEMY_TURN if item_consumed: game_state = GameStates.ENEMY_TURN if targeting: previous_game_state = GameStates.PLAYERS_TURN game_state = GameStates.TARGETING targeting_item = targeting if hasattr(targeting_item, 'item'): message_log.add_message(targeting_item.item.targeting_message) else: message_log.add_message(targeting_item.targeting_message) if ability_used: if Animator.blocking == 0: game_state = GameStates.ENEMY_TURN if item_dropped: entities.append(item_dropped) game_state = GameStates.ENEMY_TURN if equip: equip_results = player.equipment.toggle_equip(equip) for equip_result in equip_results: equipped = equip_result.get('equipped') dequipped = equip_result.get('dequipped') if equipped: message_log.add_message(Message('You equipped the {0}'.format(equipped.name))) if dequipped: message_log.add_message(Message('You removed the {0}'.format(dequipped.name))) game_state = GameStates.ENEMY_TURN if xp: leveled_up = player.level.add_xp(xp) message_log.add_message(Message('You gain {0} experience points.'.format(xp))) if leveled_up: message_log.add_message(Message('Your battle skills grow stronger! You reached level {0}'.format( player.level.current_level) + '!', libtcod.yellow)) if (player.level.current_level % 2) == 0: previous_game_state = game_state game_state = GameStates.LEVEL_UP else: hp_increase = randint(player.fighter.hitdie[0], player.fighter.hitdie[1]) + int((player.fighter.con - 10) / 2) player.fighter.base_max_hp += hp_increase player.fighter.hp += hp_increase message_log.add_message(Message('Your HP has increased by {0}'.format(hp_increase) + '!', libtcod.yellow)) # Enemy Turn if game_state == GameStates.ENEMY_TURN: for entity in entities: if entity.ai: enemy_turn_results = entity.ai.take_turn(player, fov_map, game_map, entities) # Capture enemy turn message queue, analyze and react accordingly. for enemy_turn_result in enemy_turn_results: message = enemy_turn_result.get('message') dead_entity = enemy_turn_result.get('dead') if message: message_log.add_message(message) if dead_entity: if dead_entity == player: message, game_state = kill_player(dead_entity) else: message = kill_monster(dead_entity) message_log.add_message(message) if game_state == GameStates.PLAYER_DEAD: break if game_state == GameStates.PLAYER_DEAD: break else: game_state = GameStates.PLAYERS_TURN
def play_game(player, entities, game_map, message_log, game_state, con, panel, constants): fov_recompute = True fov_map = initialize_fov(game_map) key = libtcod.Key() mouse = libtcod.Mouse() game_state = GameStates.PLAYERS_TURN previous_game_state = game_state targeting_item = None while not libtcod.console_is_window_closed(): libtcod.sys_check_for_event( libtcod.EVENT_KEY_PRESS | libtcod.EVENT_MOUSE, key, mouse) if fov_recompute: recompute_fov(fov_map, player.x, player.y, constants['fov_radius'], constants['fov_light_walls'], constants['fov_algorithm']) render_all(con, panel, entities, player, game_map, fov_map, fov_recompute, message_log, constants['screen_width'], constants['screen_height'], constants['bar_width'], constants['panel_height'], constants['panel_y'], mouse, constants['colors'], game_state) fov_recompute = False libtcod.console_flush() clear_all(con, entities) action = handle_keys(key, game_state) mouse_action = handle_mouse(mouse) move = action.get('move') wait = action.get('wait') pickup = action.get('pickup') show_inventory = action.get('show_inventory') drop_inventory = action.get('drop_inventory') inventory_index = action.get('inventory_index') take_stairs = action.get('take_stairs') level_up = action.get('level_up') show_character_screen = action.get('show_character_screen') exit = action.get('exit') fullscreen = action.get('fullscreen') left_click = mouse_action.get('left_click') right_click = mouse_action.get('right_click') player_turn_results = [] if move and game_state == GameStates.PLAYERS_TURN: dx, dy = move destination_x = player.x + dx destination_y = player.y + dy if not game_map.is_blocked(destination_x, destination_y): target = get_blocking_entities_at_location( entities, destination_x, destination_y) if target: attack_results = player.fighter.attack(target) player_turn_results.extend(attack_results) else: player.move(dx, dy) fov_recompute = True game_state = GameStates.ENEMY_TURN elif wait: game_state = GameStates.ENEMY_TURN elif pickup and game_state == GameStates.PLAYERS_TURN: for entity in entities: if entity.item and entity.x == player.x and entity.y == player.y: pickup_results = player.inventory.add_item(entity) player_turn_results.extend(pickup_results) break else: message_log.add_message( Message('There is nothing here to pick up.', libtcod.yellow)) if show_inventory: previous_game_state = game_state game_state = GameStates.SHOW_INVENTORY if drop_inventory: previous_game_state = game_state game_state = GameStates.DROP_INVENTORY if inventory_index is not None and previous_game_state != GameStates.PLAYER_DEAD and inventory_index < len( player.inventory.items): item = player.inventory.items[inventory_index] if game_state == GameStates.SHOW_INVENTORY: player_turn_results.extend( player.inventory.use(item, entities=entities, fov_map=fov_map)) elif game_state == GameStates.DROP_INVENTORY: player_turn_results.extend(player.inventory.drop_item(item)) if take_stairs and game_state == GameStates.PLAYERS_TURN: for entity in entities: if entity.stairs and entity.x == player.x and entity.y == player.y: entities = game_map.next_floor(player, message_log, constants) fov_map = initialize_fov(game_map) fov_recompute = True libtcod.console_clear(con) break else: message_log.add_message( Message('There are no stairs here.', libtcod.yellow)) if level_up: if level_up == 'hp': player.fighter.base_max_hp += 20 player.fighter.hp += 20 elif level_up == 'str': player.fighter.base_power += 1 elif level_up == 'def': player.fighter.base_defense += 1 game_state = previous_game_state if show_character_screen: previous_game_state = game_state game_state = GameStates.CHARACTER_SCREEN if game_state == GameStates.TARGETING: if left_click: target_x, target_y = left_click item_use_results = player.inventory.use(targeting_item, entities=entities, fov_map=fov_map, target_x=target_x, target_y=target_y) player_turn_results.extend(item_use_results) elif right_click: player_turn_results.append({'targeting_cancelled': True}) if exit: if game_state in (GameStates.SHOW_INVENTORY, GameStates.DROP_INVENTORY, GameStates.CHARACTER_SCREEN): game_state = previous_game_state elif game_state == GameStates.TARGETING: player_turn_results.append({'targeting_cancelled': True}) else: save_game(player, entities, game_map, message_log, game_state) return True if fullscreen: libtcod.console_set_fullscreen(not libtcod.console_is_fullscreen()) for player_turn_result in player_turn_results: message = player_turn_result.get('message') dead_entity = player_turn_result.get('dead') item_added = player_turn_result.get('item_added') item_consumed = player_turn_result.get('consumed') item_dropped = player_turn_result.get('item_dropped') equip = player_turn_result.get('equip') targeting = player_turn_result.get('targeting') targeting_cancelled = player_turn_result.get('targeting_cancelled') xp = player_turn_result.get('xp') if message: message_log.add_message(message) if dead_entity: if dead_entity == player: message, game_state = kill_player(dead_entity) else: message = kill_monster(dead_entity) message_log.add_message(message) if item_added: entities.remove(item_added) game_state = GameStates.ENEMY_TURN if item_consumed: game_state = GameStates.ENEMY_TURN if item_dropped: entities.append(item_dropped) game_state = GameStates.ENEMY_TURN if equip: equip_results = player.equipment.toggle_equip(equip) for equip_result in equip_results: equipped = equip_result.get('equipped') dequipped = equip_result.get('dequipped') if equipped: message_log.add_message( Message('You equipped the {0}'.format( equipped.name))) if dequipped: message_log.add_message( Message('You dequipped the {0}'.format( dequipped.name))) game_state = GameStates.ENEMY_TURN if targeting: previous_game_state = GameStates.PLAYERS_TURN game_state = GameStates.TARGETING targeting_item = targeting message_log.add_message(targeting_item.item.targeting_message) if targeting_cancelled: game_state = previous_game_state message_log.add_message(Message('Targeting cancelled')) if xp: leveled_up = player.level.add_xp(xp) message_log.add_message( Message('You gain {0} experience points.'.format(xp))) if leveled_up: message_log.add_message( Message( 'Your battle skills grow stronger! You reached level {0}' .format(player.level.current_level) + '!', libtcod.yellow)) previous_game_state = game_state game_state = GameStates.LEVEL_UP if game_state == GameStates.ENEMY_TURN: for entity in entities: if entity.ai: enemy_turn_results = entity.ai.take_turn( player, fov_map, game_map, entities) for enemy_turn_result in enemy_turn_results: message = enemy_turn_result.get('message') dead_entity = enemy_turn_result.get('dead') if message: message_log.add_message(message) if dead_entity: if dead_entity == player: message, game_state = kill_player(dead_entity) else: message = kill_monster(dead_entity) message_log.add_message(message) if game_state == GameStates.PLAYER_DEAD: break if game_state == GameStates.PLAYER_DEAD: break else: game_state = GameStates.PLAYERS_TURN
def main(): #define main variables constants = get_constants() # Limit FPS to 100 so we dont kill CPUs libtcod.sys_set_fps(60) # Load font and create root console (what you see) libtcod.console_set_custom_font(os.path.join(definitions.ROOT_DIR,'Nice_curses_12x12.png'), libtcod.FONT_TYPE_GREYSCALE | libtcod.FONT_LAYOUT_ASCII_INROW) libtcod.console_init_root(constants['screen_width'], constants['screen_height'], constants['window_title'], False) # Create game area and info area, this will be drawn to our root console so that we can see them con = libtcod.console_new(constants['screen_width'], constants['screen_height']) panel = libtcod.console_new(constants['screen_width'], constants['panel_height']) player = get_dummy_player(Warrior()) entities = [] game_map = None message_log: MessageLog = None game_state = None show_main_menu = True show_game = False show_load_error_message = False main_menu_background_image = libtcod.image_load(os.path.join(definitions.ROOT_DIR,'data','menu_background.png')) # Capture keyboard and mouse input key = libtcod.Key() mouse = libtcod.Mouse() mixer.init() mixer.music.load(os.path.join(definitions.ROOT_DIR, 'data', 'music', 'title.mp3')) #mixer.music.play(loops=-1) #Our main loop while not libtcod.console_is_window_closed(): # Check for input libtcod.sys_check_for_event(libtcod.EVENT_KEY_PRESS | libtcod.EVENT_MOUSE, key, mouse) if show_main_menu: main_menu(con, main_menu_background_image, constants['screen_width'], constants['screen_height']) if show_load_error_message: message_box(con, 'No save game to load', 50, constants['screen_width'], constants['screen_height']) libtcod.console_flush() action = handle_main_menu(key) new_game = action.get('new_game') load_saved_game = action.get('load_game') exit_game = action.get('exit') if show_load_error_message and (new_game or load_saved_game or exit_game): show_load_error_message = False elif new_game: show_main_menu = False show_game = True elif load_saved_game: try: player, entities, game_map, message_log, game_state = load_game() show_main_menu = False except FileNotFoundError: show_load_error_message = True elif exit_game: break elif show_game == True: action = handle_role_select(key) warrior = action.get('warrior') ranger = action.get('ranger') rogue = action.get('rogue') paladin = action.get('paladin') warlock = action.get('warlock') back = action.get('exit') accept = action.get('accept') libtcod.console_clear(0) role_menu(con,constants['screen_width'],constants['screen_height'], player.role) libtcod.console_flush() if warrior: player = get_dummy_player(Warrior()) role_menu(con,constants['screen_width'],constants['screen_height'], player.role) libtcod.console_flush() if ranger: player = get_dummy_player(Ranger()) role_menu(con,constants['screen_width'],constants['screen_height'], player.role) libtcod.console_flush() if rogue: player = get_dummy_player(Rogue()) role_menu(con,constants['screen_width'],constants['screen_height'], player.role) libtcod.console_flush() if paladin: player = get_dummy_player(Paladin()) role_menu(con,constants['screen_width'],constants['screen_height'], player.role) libtcod.console_flush() if warlock: player = get_dummy_player(Warlock()) role_menu(con,constants['screen_width'],constants['screen_height'], player.role) libtcod.console_flush() if accept: player, entities, game_map, message_log, game_state = get_game_variables(constants, player) show_game = False if back: show_main_menu = True else: libtcod.console_clear(con) game_state = GameStates.PLAYERS_TURN play_game(player, entities, game_map, message_log, game_state, con, panel, constants) show_main_menu = True
def perform(self, state, action, mouse_action, mouse_move): player_turn_result = [] exit = action.get('exit') exit_instructions = action.get('exit_instructions') move = action.get('move') pickup = action.get('pickup') show_inventory = action.get('show_inventory') inventory_index = action.get('inventory_index') shop_index = action.get('shop_index') take_stairs = action.get('take_stairs') drop_inventory = action.get('drop_inventory') targeting_cancelled = action.get('targeting_cancelled') hotkey = action.get('hotkey') # revive = action.get('revive') replay = action.get('replay') show_help = action.get('show_help') debug_take_stairs = action.get('debug_take_stairs') show_character_screen = action.get('show_character_screen') left_click = mouse_action.get('left_click') right_click = mouse_action.get('right_click') (mouse_x, mouse_y) = mouse_move if replay: player_turn_result.append({'next_stage': 'main_menu'}) if show_help: state.game_state = GameStates.INSTRUCTIONS if exit_instructions: state.game_state = GameStates.PLAYERS_TURN redraw = True self.scene.fov_recompute = True if show_inventory: if state.game_state == GameStates.INVENTORY: state.game_state = state.previous_game_state #redraw = True else: state.previous_game_state = state.game_state state.game_state = GameStates.INVENTORY if drop_inventory: if state.game_state == GameStates.DROP_INVENTORY: state.game_state = state.previous_game_state #redraw = True else: state.previous_state_game = state.game_state state.game_state = GameStates.DROP_INVENTORY if show_character_screen: if state.game_state == GameStates.CHARACTER_SCREEN: state.game_state = state.previous_game_state #redraw = True else: state.previous_game_state = state.game_state state.game_state = GameStates.CHARACTER_SCREEN if targeting_cancelled: state.game_state = state.previous_game_state state.message_log.add_message(Message('Targeting cancelled')) if shop_index is not None and shop_index < len( state.game_map.shopkeeper.shop.options): tome = state.game_map.shopkeeper.shop.options[shop_index] player_turn_result.extend(tome.use(state.player)) if inventory_index is not None and state.previous_game_state != GameStates.PLAYER_DEAD and inventory_index < len( state.player.inventory.items): item = state.player.inventory.items[inventory_index] if state.game_state == GameStates.INVENTORY: # TODO: Move fov_map to game_map player_turn_result.extend( state.player.inventory.use(item, entities=state.entities, fov_map=self.scene.fov_map)) elif state.game_state == GameStates.DROP_INVENTORY: player_turn_result.extend(state.player.inventory.drop(item)) if take_stairs and state.game_state == GameStates.PLAYERS_TURN: for entity in state.entities: if entity.stairs and entity.x == state.player.x and entity.y == state.player.y: state.entities = state.game_map.next_floor( state.player, state.message_log, CONFIG, component) self.scene.fov_map = GameScene.init_fov_map(state.game_map) self.scene.fov_recompute = True tcod.console_clear(self.scene.owner.con) break else: state.message_log.add_message( Message('No stairs found', tcod.yellow)) if debug_take_stairs: for entity in state.entities: if entity.stairs: state.entities = state.game_map.next_floor( state.player, state.message_log, CONFIG, component) self.scene.fov_map = GameScene.init_fov_map(state.game_map) self.scene.fov_recompute = True tcod.console_clear(self.scene.owner.con) if exit: if state.game_state in (GameStates.CHARACTER_SCREEN, GameStates.INVENTORY): state.game_state = state.previous_game_state redraw = True elif state.game_state == GameStates.SHOP: state.game_state = GameStates.ENEMY_TURN elif state.game_state == GameStates.TARGETING: player_turn_result.append({'targeting_cancelled': True}) else: # TODO: Port save #save_game(state.player, state.entities, state.game_map, state.message_log, state.game_state) player_turn_result.append({'exit_game': True}) if hotkey and state.game_state == GameStates.PLAYERS_TURN: results = state.player.inventory.use_hotkey( int(hotkey), entities=state.entities, fov_map=self.scene.fov_map) player_turn_result.extend(results) if move and state.game_state == GameStates.PLAYERS_TURN: dx, dy = move dest_x = state.player.x + dx dest_y = state.player.y + dy if not state.game_map.is_blocked(dest_x, dest_y): target = Entity.get_blocking(state.entities, dest_x, dest_y) if target: if target.shop: player_turn_result.append({'open_shop': True}) elif target.container: open_results = target.container.open(state.player) player_turn_result.extend(open_results) elif target.item: pickup_results = state.player.inventory.add_item( target) player_turn_result.extend(pickup_results) else: attack_results = state.player.fighter.attack(target) player_turn_result.extend(attack_results) else: state.player.move(dx, dy) self.scene.fov_recompute = True state.game_state = GameStates.ENEMY_TURN elif pickup and state.game_state == GameStates.PLAYERS_TURN: for entity in state.entities: if entity.item and entity.x == state.player.x and entity.y == state.player.y: pickup_results = state.player.inventory.add_item(entity) player_turn_result.extend(pickup_results) break else: state.message_log.add_message( Message('There is nothing here to pickup', tcod.yellow)) if state.game_state == GameStates.TARGETING: if left_click: target_x, target_y = left_click target_y = target_y - CONFIG.get('MAP_Y') # Offset item_use_results = state.player.inventory.use_hotkey( state.targeting_index, entities=state.entities, fov_map=self.scene.fov_map, target_x=target_x, target_y=target_y) player_turn_result.extend(item_use_results) elif right_click: player_turn_result.append({'targeting_cancelled': True}) self.scene.fov_recompute = True return player_turn_result
def render_all(con, panel, entities, player, game_map, fov_map, fov_recompute, message_log, screen_width, screen_height, bar_width, panel_height, panel_y, mouse, colors, game_state, camera): # Draw the tiles in the given map if fov_recompute: libtcod.console_clear( con ) # This was required to get screen scrolling working. There may be a more efficient way to update the screen but I can't think of one. for y in range(game_map.height): for x in range(game_map.width): visible = libtcod.map_is_in_fov(fov_map, x, y) wall = game_map.tiles[x][y].block_sight x_in_camera, y_in_camera = camera.apply(x, y) if visible: if wall: libtcod.console_set_char_background( con, x_in_camera, y_in_camera, colors.get('light_wall'), libtcod.BKGND_SET) else: libtcod.console_set_char_background( con, x_in_camera, y_in_camera, colors.get('light_ground'), libtcod.BKGND_SET) game_map.tiles[x][y].explored = True elif game_map.tiles[x][y].explored: if wall: libtcod.console_set_char_background( con, x_in_camera, y_in_camera, colors.get('dark_wall'), libtcod.BKGND_SET) else: libtcod.console_set_char_background( con, x_in_camera, y_in_camera, colors.get('dark_ground'), libtcod.BKGND_SET) entities_in_render_order = sorted(entities, key=lambda x: x.render_order.value) for entity in entities_in_render_order: draw_entity(con, entity, fov_map, game_map, camera) libtcod.console_blit(con, 0, 0, screen_width, screen_height, 0, 0, 0) libtcod.console_set_default_background(panel, libtcod.black) libtcod.console_clear(panel) y = 1 for message in message_log.visible: libtcod.console_set_default_foreground(panel, message.color) libtcod.console_print_ex(panel, message_log.x, y, libtcod.BKGND_NONE, libtcod.LEFT, message.text) y += 1 render_bar(panel, 1, 1, bar_width, 'HP', player.fighter.hp, player.fighter.max_hp, libtcod.light_red, libtcod.darker_red) libtcod.console_print_ex( panel, 1, 3, libtcod.BKGND_NONE, libtcod.LEFT, 'Dungeon level: {0}'.format(game_map.dungeon_level)) libtcod.console_set_default_foreground(panel, libtcod.light_gray) libtcod.console_print_ex(panel, 1, 0, libtcod.BKGND_NONE, libtcod.LEFT, get_names_under_mouse(mouse, entities, fov_map)) libtcod.console_blit(panel, 0, 0, screen_width, panel_height, 0, 0, panel_y) if game_state in (GameStates.SHOW_INVENTORY, GameStates.DROP_INVENTORY): if game_state == GameStates.SHOW_INVENTORY: inventory_title = 'Press the key next to an item to use it. Press Esc to cancel.\n' else: inventory_title = 'Press the key next to an item to drop it. Press Esc to cancel.\n' inventory_menu(con, inventory_title, player, 50, screen_width, screen_height) elif game_state == GameStates.LEVEL_UP: level_up_menu(con, 'Level up! Choose a stat to increase:', player, 40, screen_width, screen_height) elif game_state == GameStates.CHARACTER_SCREEN: character_screen( player, 30, 10, screen_width, screen_height) # TODO: More constants all over the place here elif game_state == GameStates.FULLSCREEN_CONSOLE: window = libtcod.console_new(screen_width, screen_height) z = 1 for message in message_log.fullscreen_visible: libtcod.console_set_default_foreground(window, message.color) libtcod.console_print_ex(window, 0, z, libtcod.BKGND_NONE, libtcod.LEFT, message.text) z += 1 libtcod.console_blit(window, 0, 0, screen_width, screen_height, 0, 0, 0)
def main(): constants = get_constants() # tell libtcod which font to use; dictate the file to read from, and the other two arguments tell libtcod which # type of file is being read libtcod.console_set_custom_font( 'arial10x10.png', libtcod.FONT_TYPE_GREYSCALE | libtcod.FONT_LAYOUT_TCOD) # create the screen with specified width and height; title; boolean value to say full screen or not libtcod.console_init_root(constants['screen_width'], constants['screen_height'], 'libtcod tutorial revised', False) con = libtcod.console_new(constants['screen_width'], constants['screen_height']) # create a new console to hold the HP bar and message log panel = libtcod.console_new(constants['screen_width'], constants['panel_height']) player = None entities = [] game_map = None message_log = None game_state = None show_main_menu = True show_load_error_message = False main_menu_background_image = libtcod.image_load('menu_background.png') key = libtcod.Key() mouse = libtcod.Mouse() while not libtcod.console_is_window_closed(): libtcod.sys_check_for_event( libtcod.EVENT_KEY_PRESS | libtcod.EVENT_MOUSE, key, mouse) if show_main_menu: main_menu(con, main_menu_background_image, constants['screen_width'], constants['screen_height']) if show_load_error_message: message_box(con, 'No save game to load', 50, constants['screen_width'], constants['screen_height']) libtcod.console_flush() action = handle_main_menu(key) new_game = action.get('new_game') load_saved_game = action.get('load_game') exit_game = action.get('exit') if show_load_error_message and (new_game or load_saved_game or exit_game): show_load_error_message = False elif new_game: player, entities, game_map, message_log, game_state = get_game_variables( constants) game_state = GameStates.PLAYERS_TURN show_main_menu = False elif load_saved_game: try: player, entities, game_map, message_log, game_state = load_game( ) show_main_menu = False except FileNotFoundError: show_load_error_message = True elif exit_game: break else: libtcod.console_clear(con) play_game(player, entities, game_map, message_log, game_state, con, panel, constants) show_main_menu = True
def draw_all(): T.console_clear(None) _draw_map() _draw_messages() _draw_status() T.console_flush()