def draw_loop(player, level_map, paper_map, map_console, main_console, message_console, status_console, entities, player_state): fov = player.fov(level_map, entities) re.draw_map(level_map, paper_map, map_console, fov) re.draw_all(level_map, map_console, entities, fov) re.draw_con(main_console, map_console, main_console.width - map_console.width, 0) re.draw_con(main_console, status_console, 0, 0) re.draw_con(main_console, message_console, status_console.width, main_console.height - message_console.height) tcod.console_flush() re.clear_all(level_map, map_console, entities)
def play_game(player, entities, game_map, message_log, game_state, con, panel, constants): fov_recompute = True fov_map = initialize_fov(game_map) key = tcod.Key() mouse = tcod.Mouse() game_state = GameStates.PLAYERS_TURN 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, 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 tcod.console_flush() clear_all(con, entities) action = handle_keys(key, game_state) mouse_action = handle_mouse(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') 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 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.', tcod.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 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): 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: tcod.console_set_fullscreen(not tcod.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') 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 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 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(): # initialise screen dimensions screen_width = 80 screen_height = 50 # initialise map dimensions map_width = 80 map_height = 45 # room limits and dimensions max_room_size = 10 min_room_size = 6 total_room_limit = 30 colours = { 'dark_wall': libtcod.Color(60, 49, 32), 'dark_ground': libtcod.Color(96, 128, 56), 'npc_colour': libtcod.Color(80, 80, 80) } # declare player and npcs, put them into a list player = Entity(int(screen_width / 2), int(screen_height / 2), '@', libtcod.white) npc = Entity(int(screen_width - 10 / 2), int(screen_height / 2), '$', colours.get('npc_colour')) entities = [player, npc] # initialise the map game_map = Map(map_width, map_height) game_map.create_map(total_room_limit, min_room_size, max_room_size, map_width, map_height, player) # choose font for rendering libtcod.console_set_custom_font( 'arial10x10.png', libtcod.FONT_TYPE_GREYSCALE | libtcod.FONT_LAYOUT_TCOD) # initialise console libtcod.console_init_root(screen_width, screen_height, 'Omars Roguelike', False) con = libtcod.console_new(screen_width, screen_height) # key and mouse presses key = libtcod.Key() mouse = libtcod.Mouse() while not libtcod.console_is_window_closed(): # checks for mouse or key interrupt libtcod.sys_check_for_event(libtcod.EVENT_KEY_PRESS, key, mouse) # renders all entities render_all(con, entities, screen_width, screen_height, colours, game_map) libtcod.console_flush() clear_all(con, entities) # checks what action has to be done action = handle_keys(key) move = action.get('move') exit = action.get('exit') fullscreen = action.get('fullscreen') if move: dx, dy = move if not game_map.is_blocked(player.x + dx, player.y + dy) and map_width-1 > player.x + dx > 0 and map_height-1 > \ player.y + dy > 0: player.move(dx, dy) if exit: return True if fullscreen: libtcod.console_set_fullscreen(not libtcod.console_is_fullscreen())
def do_trap(self, map, paper_map, main_console, map_console, fov, message_console, messages, entities): trap_type = self.traptype if trap_type == 0: radius = 2 for z in drawval.CHARS["floor_give"]: lc = 0 for x in range(self.x - radius, self.x + radius + 1): for y in (self.y + lc, self.y - lc): if x > -1 and x < map.width and y > -1 and y < map.height: if map.t_[x][y].type == "floor": map.t_[x][y].char = z map.t_[x][y].fg = drawval.COLORS["floor-bg"] map.t_[x][y].bg = drawval.COLORS["pit-bg"] if x < self.x: lc += 1 if x > self.x - 1: lc -= 1 fov = entities[0].fov(map, entities) re.draw_map(map, paper_map, map_console, fov) re.draw_all(map, map_console, entities, fov) re.draw_con(main_console, map_console, main_console.width - map_console.width, 0) re.draw_con(main_console, message_console, main_console.width - map_console.width, main_console.height - message_console.height) tcod.console_flush() re.clear_all(map, map_console, entities) sleep(0.050) lc = 0 for x in range(self.x - radius, self.x + radius + 1): for y in (self.y + lc, self.y - lc): if x > -1 and x < map.width and y > -1 and y < map.height: if map.t_[x][y].type == "floor": map.t_[x][y] = mp.newtile(cx.TERRAIN["pit"]) if x < self.x: lc += 1 if x > self.x - 1: lc -= 1 map.walls_and_pits() elif trap_type == 1: fov = entities[0].fov(map, entities) re.draw_map(map, paper_map, map_console, fov) re.draw_all(map, map_console, entities, fov) re.draw_con(main_console, map_console, main_console.width - map_console.width, 0) re.draw_con(main_console, message_console, main_console.width - map_console.width, main_console.height - message_console.height) tcod.console_flush() re.clear_all(map, map_console, entities) sleep(0.080) trapeffect_blocked = False while trapeffect_blocked == False: trapeffect_blocked = entities[0].move(entities[0].lastx, entities[0].lasty, map, entities, map_console, message_console, messages, True) fov = entities[0].fov(map, entities) re.draw_map(map, paper_map, map_console, fov) re.draw_all(map, map_console, entities, fov) re.draw_con(main_console, map_console, main_console.width - map_console.width, 0) re.draw_con(main_console, message_console, main_console.width - map_console.width, main_console.height - message_console.height) tcod.console_flush() re.clear_all(map, map_console, entities) sleep(0.0075) elif trap_type == 2: fov = entities[0].fov(map, entities) re.draw_map(map, paper_map, map_console, fov) re.draw_all(map, map_console, entities, fov) re.draw_con(main_console, map_console, main_console.width - map_console.width, 0) re.draw_con(main_console, message_console, main_console.width - map_console.width, main_console.height - message_console.height) tcod.console_flush() re.clear_all(map, map_console, entities) sleep(0.080) entities[0].lastx = entities[0].lastx * -1 entities[0].lasty = entities[0].lasty * -1 trapeffect_blocked = False while trapeffect_blocked == False: trapeffect_blocked = entities[0].move(entities[0].lastx, entities[0].lasty, map, entities, map_console, message_console, messages, True) fov = entities[0].fov(map, entities) re.draw_map(map, paper_map, map_console, fov) re.draw_all(map, map_console, entities, fov) re.draw_con(main_console, map_console, main_console.width - map_console.width, 0) re.draw_con(main_console, message_console, main_console.width - map_console.width, main_console.height - message_console.height) tcod.console_flush() re.clear_all(map, map_console, entities) sleep(0.0075) elif trap_type == 3: px = self.x * -1 py = self.y * -1 while map.t_[self.x + px][self.y + py].type != "floor": randz = randint(0, 4) if randz == 0: px = 1 py = 0 elif randz == 1: px = -1 py = 0 elif randz == 2: px = 0 py = -1 elif randz == 3: px = 0 py = 1 boulder = Entity(self.x + px, self.y + py, char_input=drawval.CHARS["boulder"], fg="boulder-fg", bg=cx.TERRAIN["floor"]["bg"], hp=100, speed=100, faction=cx.Faction.Enemy, draw_order=cx.DrawOrder.NPC, block_m=True, dispname="Boulder") boulder.persistent_x = px * -1 boulder.persistent_y = py * -1 entities.append(boulder) boulder.block_j = True boulder.block_s = True boulder.stats.at = 100 boulder.stats.df = 3 fov = entities[0].fov(map, entities) re.draw_map(map, paper_map, map_console, fov) re.draw_all(map, map_console, entities, fov) re.draw_con(main_console, map_console, main_console.width - map_console.width, 0) re.draw_con(main_console, message_console, main_console.width - map_console.width, main_console.height - message_console.height) tcod.console_flush() re.clear_all(map, map_console, entities) sleep(0.080) self.trapstate = -1 for event in tcod.event.wait(0.5): return
def main(): tdl.set_font('terminal16x16.png', greyscale=True, altLayout=False) # Load the font from a png. tdl.set_fps(100) map_width = 20 map_height = 20 room_width = 30 room_height = 30 screen_width = room_width + 22 screen_height = room_height + 22 root_console = tdl.init(screen_width, screen_height, title='7DRL 2019') top_panel_console = tdl.Console(screen_width, 10) view_port_console = tdl.Console(room_width, room_height) bottom_panel_console = tdl.Console(screen_width, 10) message_log = MessageLog(0, 0, screen_width, 9) entities = [] game_map = GameMap(map_width, map_height) sword_stats = Weapon(2, 10) player_weapon = Item(game_map, "0x0", 0, 0, "Sword", "|", (255, 255, 255), weapon=sword_stats) player_stats = Fighter(hits=10, left_hand=player_weapon) player = Actor(game_map, "2x2", 15, 10, "Player", "@", (255, 255, 255), fighter=player_stats) entities.append(player) generate_map(game_map, entities, player) all_consoles = [ root_console, view_port_console, bottom_panel_console, top_panel_console ] fov_algorithm = "BASIC" fov_light_walls = True fov_radius = 50 fov_recompute = True game_state = GameStates.PLAYER_TURN while not tdl.event.is_window_closed(): if fov_recompute: # Compute the field of view to show changes. game_map.rooms[player.map_x][player.map_y]\ .compute_fov(player.room_x, player.room_y, fov=fov_algorithm, radius=fov_radius, light_walls=fov_light_walls, sphere=True) render_all(all_consoles, game_map, entities, player, fov_recompute, message_log) tdl.flush() clear_all(view_port_console, entities) fov_recompute = False for event in tdl.event.get(): if event.type == 'KEYUP': user_input = event break else: user_input = None if not user_input: continue action = handle_keys(user_input) move = action.get('move') exit_game = action.get('exit_game') select_hand = action.get('select_hand') drop_item = action.get('drop_item') pickup_item = action.get('pickup_item') shuffle_rooms = action.get('shuffle_rooms') player_turn_results = [] if shuffle_rooms: message = game_map.shuffle_rooms(player, entities) message_log.add_message(message) fov_recompute = True # TODO at the moment these functions are doing all the leg work and player_turn_results isn't used. Rectify. if select_hand and game_state == GameStates.PLAYER_TURN: player.fighter.selected_hand = select_hand fov_recompute = True if drop_item and game_state == GameStates.PLAYER_TURN: message = player.fighter.drop_item(game_map, entities) message_log.add_message(message) game_state = GameStates.ENEMY_TURN fov_recompute = True if pickup_item and game_state == GameStates.PLAYER_TURN: message = player.fighter.pickup_item(entities) message_log.add_message(message) game_state = GameStates.ENEMY_TURN fov_recompute = True if move and game_state == GameStates.PLAYER_TURN: dx, dy = move destination_room_x = player.room_x + dx destination_room_y = player.room_y + dy if destination_room_x < 0: dx = 0 if player.map_x - 1 < 0: player.map_x = map_width - 1 else: player.map_x -= 1 player.room_x = room_width - 1 if destination_room_x == room_width: destination_room_x -= 1 dx = 0 if player.map_x + 1 > map_width - 1: player.map_x = 0 else: player.map_x += 1 player.room_x = 0 if destination_room_y < 0: dy = 0 if player.map_y - 1 < 0: player.map_y = map_height - 1 else: player.map_y -= 1 player.room_y = room_height - 1 if destination_room_y == room_height: destination_room_y -= 1 dy = 0 if player.map_y + 1 > map_height - 1: player.map_y = 0 else: player.map_y += 1 player.room_y = 0 if game_map.rooms[player.map_x][player.map_y].walkable[ destination_room_x, destination_room_y]: target = get_blocking_entities_at_location( entities, player.map_x, player.map_y, destination_room_x, destination_room_y) if target: # Combat here attack_results = player.fighter.attack(target) player_turn_results.extend( attack_results ) # Add the result of the last turn to the list fov_recompute = True else: player.move(dx, dy) # Or just move player.set_current_room(game_map) # TODO: Bug with the new room layouts - some cause change of room to break. print("MapPos: ", player.map_x, ",", player.map_y, end=" / ") print("RoomPos: ", player.room_x, ",", player.room_y) fov_recompute = True game_state = GameStates.ENEMY_TURN # Switch over the enemy's turn. if exit_game: return True for player_turn_result in player_turn_results: message = player_turn_result.get("message") # Pull any messages dead_entity = player_turn_result.get( "dead") # Or anything that died if message: message_log.add_message( message ) # Add the message (if any) to the message log to print on screen. if dead_entity: # If anything died... if dead_entity == player: message, game_state = kill_player(dead_entity) # Game over else: message = kill_monster( dead_entity ) # Print a death message for monster, add exp message_log.add_message(message) # Print messages to screen. player_turn_results.clear() # Clear ready for next turn. if game_state == GameStates.ENEMY_TURN: for entity in entities: if entity.map_x == player.map_x and entity.map_y == player.map_y: if entity.ai: # If the entity has some intelligence (monsters, npc) enemy_turn_results = entity.ai.take_turn( player, game_map, entities) for enemy_turn_result in enemy_turn_results: # Same deal as the player turns 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 enemy_turn_results.clear() if game_state == GameStates.PLAYER_DEAD: break else: game_state = GameStates.PLAYER_TURN