diff --git a/.gitignore b/.gitignore index 92f3c73..7f24e2b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ .idea/* *.pyc +*.dat diff --git a/camera.py b/camera.py new file mode 100644 index 0000000..c49aa27 --- /dev/null +++ b/camera.py @@ -0,0 +1,50 @@ +class Camera(): + ''' + The Game Camera that follows the player around the map. + ''' + def __init__(self, width, height, x, y): + ''' + width = the width of the window viewing the game map + + height = the height of the window viewing the game map + + (x, y) = the x and y coordinates of the game camera + ''' + self.width = width + self.height = height + self.x = x + self.y = y + + def move_camera(self, target_x, target_y, fov_recompute, game_map): + ''' + Moves the camera based on a target on the game map and then + recomputes the fov + ''' + x = int(target_x - self.width / 2) + y = int(target_y - self.height / 2) + + if x < 0: x = 0 + if y < 0: y = 0 + if x > game_map.width - self.width - 1: + x = game_map.width - self.width - 1 + if y > game_map.height - self.height - 1: + y = game_map.height - self.height - 1 + + if x != self.x or y != self.y: + fov_recompute = True + + (self.x, self.y) = (x, y) + + def to_camera_coordinates(self, x, y): + ''' + Translates the coordinates from map to camera + ''' + # (x, y) have to be int because tcod.map_is_in_fov(m, x, y) + # gives a wrong type error because it sees (x, y) as a + # float instead of an int which it requires. + (x, y) = (int(x - self.x), int(y - self.y)) + + if (x < 0 or y < 0 or x >= self.width or y >= self.height): + return (None, None) + + return (x, y) \ No newline at end of file diff --git a/engine.py b/engine.py index e43caf4..9ccf155 100644 --- a/engine.py +++ b/engine.py @@ -1,5 +1,6 @@ import libtcodpy as libtcod +from camera import Camera from death_functions import kill_monster, kill_player from entity import get_blocking_entities_at_location from fov_functions import initialize_fov, recompute_fov @@ -25,6 +26,8 @@ def play_game(player, entities, game_map, message_log, game_state, con, panel, c targeting_item = None + camera = Camera(constants['camera_width'], constants['camera_height'], 0, 0) + while not libtcod.console_is_window_closed(): libtcod.sys_check_for_event(libtcod.EVENT_KEY_PRESS | libtcod.EVENT_MOUSE, key, mouse) @@ -34,13 +37,14 @@ def play_game(player, entities, game_map, message_log, game_state, con, panel, c 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) + constants['panel_height'], constants['panel_y'], mouse, constants['colors'], game_state, + camera) fov_recompute = False libtcod.console_flush() - clear_all(con, entities) + clear_all(con, entities, camera) action = handle_keys(key, game_state) mouse_action = handle_mouse(mouse) @@ -139,7 +143,8 @@ def play_game(player, entities, game_map, message_log, game_state, con, panel, c if game_state == GameStates.TARGETING: if left_click: - target_x, target_y = left_click + (target_x, target_y) = left_click + (target_x, target_y) = (camera.x + target_x, camera.y + target_y) item_use_results = player.inventory.use(targeting_item, entities=entities, fov_map=fov_map, target_x=target_x, target_y=target_y) diff --git a/loader_functions/initialize_new_game.py b/loader_functions/initialize_new_game.py index 879c17d..2c57de4 100644 --- a/loader_functions/initialize_new_game.py +++ b/loader_functions/initialize_new_game.py @@ -34,11 +34,14 @@ def get_constants(): message_height = panel_height - 1 map_width = 80 - map_height = 43 + map_height = 80 + + camera_width = 80 + camera_height = 43 room_max_size = 10 room_min_size = 6 - max_rooms = 30 + max_rooms = 50 fov_algorithm = 0 fov_light_walls = True @@ -74,7 +77,9 @@ def get_constants(): 'fov_radius': fov_radius, 'max_monsters_per_room': max_monsters_per_room, 'max_items_per_room': max_items_per_room, - 'colors': colors + 'colors': colors, + 'camera_width': camera_width, + 'camera_height': camera_height } return constants diff --git a/render_functions.py b/render_functions.py index 42c9089..b8884ca 100644 --- a/render_functions.py +++ b/render_functions.py @@ -14,8 +14,9 @@ class RenderOrder(Enum): ACTOR = 4 -def get_names_under_mouse(mouse, entities, fov_map): +def get_names_under_mouse(mouse, entities, fov_map, camera): (x, y) = (mouse.cx, mouse.cy) + (x, y) = (camera.x + x, camera.y + y) names = [entity.name for entity in entities if entity.x == x and entity.y == y and libtcod.map_is_in_fov(fov_map, entity.x, entity.y)] @@ -40,13 +41,16 @@ def render_bar(panel, x, y, total_width, name, value, maximum, bar_color, back_c 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): + bar_width, panel_height, panel_y, mouse, colors, game_state, + camera): + camera.move_camera(player.x, player.y, fov_recompute, game_map) if fov_recompute: # Draw all the tiles in the game map - 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 + for y in range(camera.height): + for x in range(camera.width): + (map_x, map_y) = (camera.x + x, camera.y + y) + visible = libtcod.map_is_in_fov(fov_map, map_x, map_y) + wall = game_map.tiles[map_x][map_y].block_sight if visible: if wall: @@ -54,18 +58,25 @@ def render_all(con, panel, entities, player, game_map, fov_map, fov_recompute, m 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: + game_map.tiles[map_x][map_y].explored = True + elif game_map.tiles[map_x][map_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) + else: + # Needed so the map renders correctly since previously + # the map did not move any place not seen would stay dark + # now the map moves and areas that should not be seen are + # being seen. + libtcod.console_set_char_background(con, x, y, libtcod.black, + 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) + draw_entity(con, entity, fov_map, game_map, camera) libtcod.console_blit(con, 0, 0, screen_width, screen_height, 0, 0, 0) @@ -86,7 +97,7 @@ def render_all(con, panel, entities, player, game_map, fov_map, fov_recompute, m 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)) + get_names_under_mouse(mouse, entities, fov_map, camera)) libtcod.console_blit(panel, 0, 0, screen_width, panel_height, 0, 0, panel_y) @@ -105,17 +116,21 @@ def render_all(con, panel, entities, player, game_map, fov_map, fov_recompute, m character_screen(player, 30, 10, screen_width, screen_height) -def clear_all(con, entities): +def clear_all(con, entities, camera): for entity in entities: - clear_entity(con, entity) + clear_entity(con, entity, camera) -def draw_entity(con, entity, fov_map, game_map): +def draw_entity(con, entity, fov_map, game_map, camera): if libtcod.map_is_in_fov(fov_map, entity.x, entity.y) or (entity.stairs and game_map.tiles[entity.x][entity.y].explored): - libtcod.console_set_default_foreground(con, entity.color) - libtcod.console_put_char(con, entity.x, entity.y, entity.char, libtcod.BKGND_NONE) + (x, y) = camera.to_camera_coordinates(entity.x, entity.y) + if x is not None: + libtcod.console_set_default_foreground(con, entity.color) + libtcod.console_put_char(con, x, y, entity.char, libtcod.BKGND_NONE) -def clear_entity(con, entity): - # erase the character that represents this object - libtcod.console_put_char(con, entity.x, entity.y, ' ', libtcod.BKGND_NONE) +def clear_entity(con, entity, camera): + (x, y) = camera.to_camera_coordinates(entity.x, entity.y) + if x is not None: + # erase the character that represents this object + libtcod.console_put_char(con, x, y, ' ', libtcod.BKGND_NONE)