Working visibility and displaying it, still need to hide things that aren't visible

This commit is contained in:
Nicolas Margulies 2020-12-18 17:04:45 +01:00
parent 62ce2b5c71
commit 86628fdea6
4 changed files with 64 additions and 41 deletions

View File

@ -15,8 +15,15 @@ class MapDisplay(Display):
self.pad = self.newpad(m.height, self.pack.tile_width * m.width + 1)
def update_pad(self) -> None:
self.addstr(self.pad, 0, 0, self.map.draw_string(self.pack),
self.pack.tile_fg_color, self.pack.tile_bg_color)
for j in range(len(self.map.tiles)):
for i in range(len(self.map.tiles[j])):
color = self.pack.tile_fg_visible_color if \
self.map.visibility[j][i] else self.pack.tile_fg_color
self.addstr(self.pad, j, self.pack.tile_width * i,
self.map.tiles[j][i].char(self.pack),
color, self.pack.tile_bg_color)
# self.addstr(self.pad, 0, 0, self.map.draw_string(self.pack),
# self.pack.tile_fg_color, self.pack.tile_bg_color)
for e in self.map.entities:
self.addstr(self.pad, e.y, self.pack.tile_width * e.x,
self.pack[e.name.upper()],

View File

@ -2,7 +2,7 @@
# SPDX-License-Identifier: GPL-3.0-or-later
import curses
from typing import Any
from typing import Any, Union, Tuple
class TexturePack:
@ -10,10 +10,11 @@ class TexturePack:
name: str
tile_width: int
tile_fg_color: int
tile_bg_color: int
entity_fg_color: int
entity_bg_color: int
tile_fg_color: Union[int, Tuple[int, int, int]]
tile_fg_visible_color: Union[int, Tuple[int, int, int]]
tile_bg_color: Union[int, Tuple[int, int, int]]
entity_fg_color: Union[int, Tuple[int, int, int]]
entity_bg_color: Union[int, Tuple[int, int, int]]
BODY_SNATCH_POTION: str
BOMB: str
@ -54,9 +55,10 @@ class TexturePack:
TexturePack.ASCII_PACK = TexturePack(
name="ascii",
tile_width=1,
tile_fg_visible_color=(1000, 1000, 1000),
tile_fg_color=curses.COLOR_WHITE,
tile_bg_color=curses.COLOR_BLACK,
entity_fg_color=curses.COLOR_WHITE,
entity_fg_color=(1000, 1000, 1000),
entity_bg_color=curses.COLOR_BLACK,
BODY_SNATCH_POTION='S',
@ -80,10 +82,11 @@ TexturePack.ASCII_PACK = TexturePack(
TexturePack.SQUIRREL_PACK = TexturePack(
name="squirrel",
tile_width=2,
tile_fg_visible_color=(1000, 1000, 1000),
tile_fg_color=curses.COLOR_WHITE,
tile_bg_color=curses.COLOR_BLACK,
entity_fg_color=curses.COLOR_WHITE,
entity_bg_color=curses.COLOR_WHITE,
entity_fg_color=(1000, 1000, 1000),
entity_bg_color=(1000, 1000, 1000),
BODY_SNATCH_POTION='🔀',
BOMB='💣',

View File

@ -21,7 +21,7 @@ class Player(InventoryHolder, FightingEntity):
strength: int = 5, intelligence: int = 1, charisma: int = 1,
dexterity: int = 1, constitution: int = 1, level: int = 1,
current_xp: int = 0, max_xp: int = 10, inventory: list = None,
hazel: int = 42, *args, **kwargs) \
hazel: int = 42, vision: int = 5, *args, **kwargs) \
-> None:
super().__init__(name=name, maxhealth=maxhealth, strength=strength,
intelligence=intelligence, charisma=charisma,
@ -32,6 +32,7 @@ class Player(InventoryHolder, FightingEntity):
self.inventory = self.translate_inventory(inventory or [])
self.paths = dict()
self.hazel = hazel
self.vision = vision
def move(self, y: int, x: int) -> None:
"""
@ -42,6 +43,7 @@ class Player(InventoryHolder, FightingEntity):
self.map.currenty = y
self.map.currentx = x
self.recalculate_paths()
self.map.compute_visibility(self.y, self.x, self.vision)
def level_up(self) -> None:
"""

View File

@ -4,7 +4,8 @@
from enum import Enum, auto
from math import sqrt
from random import choice, randint
from typing import List, Optional, Union, Tuple, Any
from typing import List, Optional, Tuple, Any
from math import ceil
from .display.texturepack import TexturePack
from .translations import gettext as _
@ -38,19 +39,25 @@ class Slope():
self.Y = y
self.X = x
def compare(self, other: Union[Tuple[int, int], "Slope"]) -> int:
if isinstance(other, Slope):
def compare(self, other: "Slope") -> int:
y, x = other.Y, other.X
else:
y, x = other
return self.Y * x - self.X * y
def __lt__(self, other: Union[Tuple[int, int], "Slope"]) -> bool:
def __lt__(self, other: "Slope") -> bool:
return self.compare(other) < 0
def __eq__(self, other: Union[Tuple[int, int], "Slope"]) -> bool:
def __eq__(self, other: "Slope") -> bool:
return self.compare(other) == 0
def __gt__(self, other: "Slope") -> bool:
return self.compare(other) > 0
def __le__(self, other: "Slope") -> bool:
return self.compare(other) <= 0
def __ge__(self, other: "Slope") -> bool:
return self.compare(other) >= 0
class Map:
"""
@ -194,16 +201,16 @@ class Map:
if top.X == 1:
top_y = x
else:
top_y = ((x * 2 - 1) * top.Y + top.X) / (top.X * 2)
top_y = ceil(((x * 2 - 1) * top.Y + top.X) / (top.X * 2))
if self.is_wall(top_y, x, octant, origin):
if top >= (top_y * 2 + 1, x * 2) and not\
if top >= Slope(top_y * 2 + 1, x * 2) and not\
self.is_wall(top_y + 1, x, octant, origin):
top_y += 1
else:
ax = x * 2
if self.is_wall(top_y + 1, x + 1, octant, origin):
ax += 1
if top > (top_y * 2 + 1, ax):
if top > Slope(top_y * 2 + 1, ax):
top_y += 1
return top_y
@ -212,9 +219,9 @@ class Map:
if bottom.Y == 0:
bottom_y = 0
else:
bottom_y = ((x * 2 + 1) * bottom.Y + bottom.X) /\
(bottom.X * 2)
if bottom >= (bottom_y * 2 + 1, x * 2) and\
bottom_y = ceil(((x * 2 - 1) * bottom.Y + bottom.X)
/ (bottom.X * 2))
if bottom >= Slope(bottom_y * 2 + 1, x * 2) and\
self.is_wall(bottom_y, x, octant, origin) and\
not self.is_wall(bottom_y + 1, x, octant, origin):
bottom_y += 1
@ -223,17 +230,18 @@ class Map:
def compute_visibility_octant(self, octant: int, origin: Tuple[int, int],
max_range: int, distance: int, top: Slope,
bottom: Slope) -> None:
for x in range(distance, max_range):
for x in range(distance, max_range + 1):
top_y = self.crop_top_visibility(octant, origin, x, top)
bottom_y = self.crop_bottom_visibility(octant, origin, x, bottom)
was_opaque = -1
for y in range(top_y, bottom_y - 1, -1):
if sqrt(x**2 + y**2) > max_range:
if x + y > max_range:
continue
is_opaque = self.is_wall(y, x, octant, origin)
is_visible = is_opaque\
or ((y != top_y or top > (y * 4 - 1, x * 4 - 1))
and (y != bottom_y or bottom < (y * 4 + 1, x * 4 + 1)))
or ((y != top_y or top > Slope(y * 4 - 1, x * 4 + 1))
and (y != bottom_y
or bottom < Slope(y * 4 + 1, x * 4 - 1)))
if is_visible:
self.set_visible(y, x, octant, origin)
if x == max_range:
@ -242,7 +250,7 @@ class Map:
nx, ny = x * 2, y * 2 + 1
if self.is_wall(y + 1, x, octant, origin):
nx -= 1
if top > (ny, nx):
if top > Slope(ny, nx):
if y == bottom_y:
bottom = Slope(ny, nx)
break
@ -257,8 +265,9 @@ class Map:
nx, ny = x * 2, y * 2 + 1
if self.is_wall(y + 1, x + 1, octant, origin):
nx += 1
if bottom >= (ny, nx):
if bottom >= Slope(ny, nx):
return
top = Slope(ny, nx)
was_opaque = is_opaque
if was_opaque != 0:
break
@ -268,30 +277,32 @@ class Map:
origin: Tuple[int, int]) -> Tuple[int, int]:
ny, nx = origin
if octant == 0:
return nx + x, ny - y
return ny - y, nx + x
elif octant == 1:
return nx + y, ny - x
return ny - x, nx + y
elif octant == 2:
return nx - y, ny - x
return ny - x, nx - y
elif octant == 3:
return nx - x, ny - y
return ny - y, nx - x
elif octant == 4:
return nx - x, ny + y
return ny + y, nx - x
elif octant == 5:
return nx - y, ny + x
return ny + x, nx - y
elif octant == 6:
return nx + y, ny + x
return ny + x, nx + y
elif octant == 7:
return nx + x, ny + y
return ny + y, nx + x
def is_wall(self, y: int, x: int, octant: int,
origin: Tuple[int, int]) -> bool:
y, x = self.translate_coord(y, x, octant, origin)
return self.tiles[y][x].is_wall()
return 0 <= y < len(self.tiles) and 0 <= x < len(self.tiles[0]) and \
self.tiles[y][x].is_wall()
def set_visible(self, y: int, x: int, octant: int,
origin: Tuple[int, int]) -> None:
y, x = self.translate_coord(y, x, octant, origin)
if 0 <= y < len(self.tiles) and 0 <= x < len(self.tiles[0]):
self.visibility[y][x] = True
def tick(self) -> None: