- Move all map rendering to a new MapWindow class - Clip map rendering to the bounds of the Window - Pass in Entities list from the Engine and render them relative to the window The map doesn't scroll yet, so it'll always be clipped on the bottom and right.
93 lines
2.9 KiB
Python
93 lines
2.9 KiB
Python
# Eryn Wells <eryn@erynwells.me>
|
|
|
|
from typing import List
|
|
|
|
import numpy as np
|
|
from tcod.console import Console
|
|
|
|
from ..object import Entity
|
|
from ..geometry import Rect, Vector
|
|
from ..map import Map
|
|
|
|
|
|
class Window:
|
|
'''A user interface window. It can be framed.'''
|
|
|
|
def __init__(self, bounds: Rect, *, framed: bool = True):
|
|
self.bounds = bounds
|
|
self.is_framed = framed
|
|
|
|
@property
|
|
def drawable_bounds(self) -> Rect:
|
|
if self.is_framed:
|
|
return self.bounds.inset_rect(1, 1, 1, 1)
|
|
return self.bounds
|
|
|
|
def draw(self, console: Console):
|
|
if self.is_framed:
|
|
console.draw_frame(
|
|
self.bounds.origin.x,
|
|
self.bounds.origin.y,
|
|
self.bounds.size.width,
|
|
self.bounds.size.height)
|
|
|
|
|
|
class MapWindow(Window):
|
|
'''A Window that displays a game map'''
|
|
|
|
def __init__(self, bounds: Rect, map_: Map, **kwargs):
|
|
super().__init__(bounds, **kwargs)
|
|
self.map = map_
|
|
|
|
self.entities: List[Entity] = []
|
|
|
|
def draw(self, console: Console):
|
|
super().draw(console)
|
|
self._draw_map(console)
|
|
self._draw_entities(console)
|
|
|
|
def _draw_map(self, console: Console):
|
|
map_ = self.map
|
|
map_size = map_.size
|
|
|
|
drawable_bounds = self.drawable_bounds
|
|
|
|
width = min(map_size.width, drawable_bounds.width)
|
|
height = min(map_size.height, drawable_bounds.height)
|
|
|
|
# TODO: Adjust the slice according to where the hero is.
|
|
map_slice = np.s_[0:width, 0:height]
|
|
|
|
min_x = drawable_bounds.min_x
|
|
max_x = min_x + width
|
|
min_y = drawable_bounds.min_y
|
|
max_y = min_y + height
|
|
|
|
console.tiles_rgb[min_x:max_x, min_y:max_y] = self.map.composited_tiles[map_slice]
|
|
|
|
def _draw_entities(self, console):
|
|
drawable_bounds_vector = Vector.from_point(self.drawable_bounds.origin)
|
|
|
|
for ent in self.entities:
|
|
# Only process entities that are in the field of view
|
|
if not self.map.visible[tuple(ent.position)]:
|
|
continue
|
|
|
|
# Entity positions are 0-based relative to the (0, 0) point of the Map. In order to render them in the
|
|
# correct position in the console, we need to offset the position.
|
|
entity_position = ent.position
|
|
map_tile_at_entity_position = self.map.composited_tiles[entity_position.x, entity_position.y]
|
|
|
|
position = ent.position + drawable_bounds_vector
|
|
console.print(
|
|
x=position.x,
|
|
y=position.y,
|
|
string=ent.symbol,
|
|
fg=ent.foreground,
|
|
bg=tuple(map_tile_at_entity_position['bg'][:3]))
|
|
|
|
# if ent.position == self.__current_mouse_point:
|
|
# entities_at_mouse_position.append(ent)
|
|
|
|
# if len(entities_at_mouse_position) > 0:
|
|
# console.print(x=1, y=43, string=', '.join(e.name for e in entities_at_mouse_position))
|