|
2 | 2 | Path-related functions.
|
3 | 3 |
|
4 | 4 | """
|
| 5 | +from shapely import speedups |
| 6 | +from shapely.geometry import LineString, Polygon |
| 7 | + |
5 | 8 | from arcade import Point
|
6 |
| -from arcade import get_distance |
7 |
| -from arcade import lerp_vec |
8 |
| -from arcade import get_sprites_at_point |
9 | 9 | from arcade import check_for_collision_with_list
|
10 | 10 | from arcade import Sprite
|
11 | 11 | from arcade import SpriteList
|
12 | 12 |
|
| 13 | + |
| 14 | +speedups.enable() |
| 15 | + |
| 16 | + |
13 | 17 | def has_line_of_sight(point_1: Point,
|
14 | 18 | point_2: Point,
|
15 | 19 | walls: SpriteList,
|
16 |
| - max_distance: int = -1, |
17 |
| - check_resolution: int = 2): |
| 20 | + max_distance: int = -1): |
18 | 21 | """
|
19 |
| - Determine if we have line of sight between two points. Try to make sure |
20 |
| - that spatial hashing is enabled on the wall SpriteList or this will be |
21 |
| - very slow. |
22 |
| -
|
23 |
| - :param Point point_1: Start position |
24 |
| - :param Point point_2: End position position |
25 |
| - :param SpriteList walls: List of all blocking sprites |
26 |
| - :param int max_distance: Max distance point 1 can see |
27 |
| - :param int check_resolution: Check every x pixels for a sprite. Trade-off |
28 |
| - between accuracy and speed. |
| 22 | + Determine if we have line of sight between two points. Having a line of |
| 23 | + sight means, that you can connect both points with straight line without |
| 24 | + intersecting any obstacle. |
| 25 | + Thanks to the shapely efficiency and speedups boost, this method is very |
| 26 | + fast. It can easily test 10 000 lines_of_sight. |
| 27 | +
|
| 28 | + :param point_1: tuple -- coordinates of first position (x, y) |
| 29 | + :param point_2: tuple -- coordinates of second position (x, y) |
| 30 | + :param walls: list -- Obstacle objects to check against |
| 31 | + :param max_distance: int -- |
| 32 | + :return: tuple -- (bool, list) |
29 | 33 | """
|
30 |
| - distance = get_distance(point_1[0], point_1[1], |
31 |
| - point_2[0], point_2[1]) |
32 |
| - steps = int(distance // check_resolution) |
33 |
| - for step in range(steps + 1): |
34 |
| - step_distance = step * check_resolution |
35 |
| - u = step_distance / distance |
36 |
| - midpoint = lerp_vec(point_1, point_2, u) |
37 |
| - if max_distance != -1 and step_distance > max_distance: |
38 |
| - return False |
39 |
| - # print(point_1, point_2, step, u, step_distance, midpoint) |
40 |
| - sprite_list = get_sprites_at_point(midpoint, walls) |
41 |
| - if len(sprite_list) > 0: |
42 |
| - return False |
43 |
| - return True |
| 34 | + if not walls: |
| 35 | + return True |
| 36 | + line_of_sight = LineString([point_1, point_2]) |
| 37 | + if 0 < max_distance < line_of_sight.length: |
| 38 | + return False |
| 39 | + return not any((Polygon(o.get_adjusted_hit_box()).crosses(line_of_sight) for o in walls)) |
44 | 40 |
|
45 | 41 |
|
46 | 42 | """
|
47 | 43 | Classic A-star algorithm for path finding.
|
48 | 44 | """
|
49 | 45 |
|
| 46 | + |
50 | 47 | def _spot_is_blocked(position, moving_sprite, blocking_sprites):
|
51 | 48 | original_pos = moving_sprite.position
|
52 | 49 | moving_sprite.position = position
|
|
0 commit comments