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

@ -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):
y, x = other.Y, other.X
else:
y, x = other
def compare(self, other: "Slope") -> int:
y, x = other.Y, other.X
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,31 +277,33 @@ 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)
self.visibility[y][x] = True
if 0 <= y < len(self.tiles) and 0 <= x < len(self.tiles[0]):
self.visibility[y][x] = True
def tick(self) -> None:
"""