-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathfov_shapely.py
100 lines (89 loc) · 3.81 KB
/
fov_shapely.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
from typing import List, NamedTuple
from shapely.geometry import MultiPoint, MultiPolygon, Polygon, box
from shapely import speedups
class Coordinates(NamedTuple):
x: float
y: float
def is_visible(player: Coordinates, tile: Coordinates, blocking_tiles: List[Coordinates]) -> bool:
# take the convex hull of the player's eyes and the corners of the tile
fov_polygon = MultiPoint([
(player.x + 0.5, player.y + 0.5),
(tile.x, tile.y),
(tile.x + 1, tile.y),
(tile.x + 1, tile.y + 1),
(tile.x, tile.y + 1),
]).convex_hull
# carve out all the blocking tiles
for bt in blocking_tiles:
blocking_box = box(bt.x, bt.y, bt.x + 1, bt.y + 1)
fov_polygon = fov_polygon.difference(blocking_box)
if isinstance(fov_polygon, MultiPolygon):
return False
return True
# where the player tile is
player_x, player_y = 5.0, 5.0
# where the players "eyes" are - this is where we will trace back to
eyes_x, eyes_y = player_x + 0.5, player_y + 0.5
# blocking tile
blocking_x, blocking_y = 6.0, 6.0
blocking_box = box(blocking_x, blocking_y, blocking_x+1, blocking_y+1)
print('TILE 1')
# tile we want to check for visibility - should be blocked
tile1_x, tile1_y = 7.0, 7.0
# take the convex hull of the player's eyes and the corners of the tile
tile1_fov_polygon = MultiPoint([
(eyes_x, eyes_y),
(tile1_x, tile1_y),
(tile1_x+1, tile1_y),
(tile1_x+1, tile1_y+1),
(tile1_x, tile1_y+1),
]).convex_hull
print(tile1_fov_polygon)
# find all of the blocking boxes that intersect that convex hull polygon
print(blocking_box.intersects(tile1_fov_polygon))
# take the difference of the convex hull and the intersecting boxes
print(tile1_fov_polygon.difference(blocking_box))
# you know the tile is blocked as soon as you wind up with a multipolygon
print(type(tile1_fov_polygon.difference(blocking_box)))
# which is already the case here
print('is_visible?', is_visible(Coordinates(player_x, player_y), Coordinates(tile1_x, tile1_y), [Coordinates(blocking_x, blocking_y)]))
print('\nTILE 2')
# another tile to check for visibility - should be visible
tile2_x, tile2_y = 5.0, 6.0
# take the convex hull of the player's eyes and the corners of the tile
tile2_fov_polygon = MultiPoint([
(eyes_x, eyes_y),
(tile2_x, tile2_y),
(tile2_x+1, tile2_y),
(tile2_x+1, tile2_y+1),
(tile2_x, tile2_y+1),
]).convex_hull
print(tile2_fov_polygon)
# find all of the blocking boxes that intersect that convex hull polygon
print(blocking_box.intersects(tile2_fov_polygon))
# take the difference of the convex hull and the intersecting boxes
print(tile2_fov_polygon.difference(blocking_box))
# you know the tile is blocked as soon as you wind up with a multipolygon
print(type(tile2_fov_polygon.difference(blocking_box)))
# but here that's not the case
print('is_visible?', is_visible(Coordinates(player_x, player_y), Coordinates(tile2_x, tile2_y), [Coordinates(blocking_x, blocking_y)]))
print('\nTILE 3')
# another tile to check for visibility - should be visible
tile3_x, tile3_y = 6.0, 7.0
# take the convex hull of the player's eyes and the corners of the tile
tile3_fov_polygon = MultiPoint([
(eyes_x, eyes_y),
(tile3_x, tile3_y),
(tile3_x+1, tile3_y),
(tile3_x+1, tile3_y+1),
(tile3_x, tile3_y+1),
]).convex_hull
print(tile3_fov_polygon)
# find all of the blocking boxes that intersect that convex hull polygon
print(blocking_box.intersects(tile3_fov_polygon))
# take the difference of the convex hull and the intersecting boxes
print(tile3_fov_polygon.difference(blocking_box))
# you know the tile is blocked as soon as you wind up with a multipolygon
print(type(tile3_fov_polygon.difference(blocking_box)))
# but here that's not the case
print('is_visible?', is_visible(Coordinates(player_x, player_y), Coordinates(tile3_x, tile3_y), [Coordinates(blocking_x, blocking_y)]))