From 084385f8f2bc2c1abd8eea130acbc0f48b03a5c9 Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Wed, 4 May 2022 09:22:40 -0700 Subject: [PATCH] Add a map shroud over tiles and compute field of view based on player position!!! --- roguebasin/engine.py | 17 +++++++++++++++++ roguebasin/map.py | 16 ++++++++++++++-- roguebasin/tile.py | 25 ++++++++++++++++++++----- 3 files changed, 51 insertions(+), 7 deletions(-) diff --git a/roguebasin/engine.py b/roguebasin/engine.py index 0eb13c1..d85cf71 100644 --- a/roguebasin/engine.py +++ b/roguebasin/engine.py @@ -37,6 +37,8 @@ class Engine: position = self.map.random_walkable_position() self.entities.add(Entity('@', position=position, fg=tcod.yellow)) + self.update_field_of_view() + def handle_event(self, event: tcod.event.Event): action = self.event_handler.dispatch(event) @@ -45,8 +47,23 @@ class Engine: action.perform(self, self.player) + self.update_field_of_view() + def print_to_console(self, console): self.map.print_to_console(console) for ent in self.entities: + # Only print entities that are in the field of view + if not self.map.visible[tuple(ent.position)]: + continue ent.print_to_console(console) + + def update_field_of_view(self) -> None: + '''Compute visible area of the map based on the player's position and point of view.''' + self.map.visible[:] = tcod.map.compute_fov( + self.map.tiles['transparent'], + tuple(self.player.position), + radius=8) + + # Visible tiles should be added to the explored list + self.map.explored |= self.map.visible diff --git a/roguebasin/map.py b/roguebasin/map.py index 14611c4..58bd27b 100644 --- a/roguebasin/map.py +++ b/roguebasin/map.py @@ -6,7 +6,7 @@ import numpy as np import random import tcod from .geometry import Direction, Point, Rect, Size -from .tile import Empty, Floor, Wall +from .tile import Empty, Floor, Shroud, Wall from dataclasses import dataclass from typing import Iterator, List, Optional @@ -19,6 +19,11 @@ class Map: self.generator = RoomsAndCorridorsGenerator(size=size) self.tiles = self.generator.generate() + # Map tiles that are currently visible to the player + self.visible = np.full(tuple(self.size), fill_value=False, order='F') + # Map tiles that the player has explored + self.explored = np.full(tuple(self.size), fill_value=False, order='F') + def random_walkable_position(self) -> Point: # TODO: Include hallways random_room: RectangularRoom = random.choice(self.generator.rooms) @@ -34,8 +39,15 @@ class Map: return self.tiles[point.x, point.y]['walkable'] def print_to_console(self, console: tcod.Console) -> None: + '''Render the map to the console.''' size = self.size - console.tiles_rgb[0:size.width, 0:size.height] = self.tiles["dark"] + + # If a tile is in the visible array, draw it with the "light" color. If it's not, but it's in the explored + # array, draw it with the "dark" color. Otherwise, draw it as Empty. + console.tiles_rgb[0:size.width, 0:size.height] = np.select( + condlist=[self.visible, self.explored], + choicelist=[self.tiles['light'], self.tiles['dark']], + default=Shroud) class MapGenerator: def __init__(self, *, size: Size): diff --git a/roguebasin/tile.py b/roguebasin/tile.py index 7048a50..07fa0a3 100644 --- a/roguebasin/tile.py +++ b/roguebasin/tile.py @@ -20,11 +20,26 @@ tile_datatype = np.dtype([ ('transparent', np.bool), # A graphic struct (as above) defining the look of this tile when it's not visible ('dark', graphic_datatype), + # A graphic struct (as above) defining the look of this tile when it's visible + ('light', graphic_datatype), ]) -def tile(*, walkable: int, transparent: int, dark: Tuple[int, Tuple[int, int, int], Tuple[int, int ,int]]) -> np.ndarray: - return np.array((walkable, transparent, dark), dtype=tile_datatype) +def tile(*, + walkable: int, + transparent: int, + dark: Tuple[int, Tuple[int, int, int], Tuple[int, int ,int]], + light: Tuple[int, Tuple[int, int, int], Tuple[int, int ,int]]) -> np.ndarray: + return np.array((walkable, transparent, dark, light), dtype=tile_datatype) -Empty = tile(walkable=False, transparent=False, dark=(ord(' '), (255, 255, 255), (0, 0, 0))) -Floor = tile(walkable=True, transparent=True, dark=(ord(' '), (255, 255, 255), (50, 50, 150))) -Wall = tile(walkable=False, transparent=False, dark=(ord(' '), (255, 255, 255), (0, 0, 150))) \ No newline at end of file +# An overlay color for tiles that are not visible and have not been explored +Shroud = np.array((ord(' '), (255, 255, 255), (0, 0, 0)), dtype=graphic_datatype) + +Empty = tile(walkable=False, transparent=False, + dark=(ord(' '), (255, 255, 255), (0, 0, 0)), + light=(ord(' '), (255, 255, 255), (0, 0, 0))) +Floor = tile(walkable=True, transparent=True, + dark=(ord('·'), (80, 80, 100), (50, 50, 50)), + light=(ord('·'), (100, 100, 120), (80, 80, 100))) +Wall = tile(walkable=False, transparent=False, + dark=(ord(' '), (255, 255, 255), (0, 0, 150)), + light=(ord(' '), (255, 255, 255), (50, 50, 200))) \ No newline at end of file