-
Notifications
You must be signed in to change notification settings - Fork 0
/
RayCasting.py
75 lines (62 loc) · 2.68 KB
/
RayCasting.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
from math import atan2, cos, sin, sqrt, radians, degrees
from numba import njit
@njit(fastmath=True)
def ray_cycle(player_x, player_y, view_angle, obstacles, tile_w, tile_h, map_w, map_h, fov, rays):
rounded_x = (player_x // tile_w) * tile_w
rounded_y = (player_y // tile_h) * tile_h
coords = []
period = (fov / rays)
for ray in range(-rays // 2, rays // 2 + 1): # Цикл по углу обзора
alpha = view_angle + radians(ray * period)
sin_a = sin(alpha) if sin(alpha) else 0.000001
cos_a = cos(alpha) if cos(alpha) else 0.000001
view_cos = cos(view_angle - alpha)
ray_x, ray_y = player_x, player_y
# Пересечение по вертикали
ray_x, dx = (rounded_x + tile_w, 1) if cos_a >= 0 else (rounded_x, -1)
found = False
for _ in range(0, map_w * tile_w, tile_w):
length_v = (ray_x - player_x) / cos_a
ray_y = player_y + length_v * sin_a
for ox, oy, map_w, map_h in obstacles:
if ox <= ray_x <= ox + map_w and oy <= ray_y <= oy + map_h:
found = True
break
if found:
break
ray_x += tile_w * dx
res_v = (int(ray_x), int(ray_y), length_v * view_cos)
# Пересечение по горизонтали
ray_y, dy = (rounded_y + tile_h, 1) if sin_a >= 0 else (rounded_y, -1)
found = False
for _ in range(0, map_h * tile_h, tile_h):
length_h = (ray_y - player_y) / sin_a
ray_x = player_x + length_h * cos_a
for ox, oy, map_w, map_h in obstacles:
if ox <= ray_x <= ox + map_w and oy <= ray_y <= oy + map_h:
found = True
break
if found:
break
ray_y += tile_h * dy
res_h = (int(ray_x), int(ray_y), length_h * view_cos)
res = res_v if res_v[2] <= res_h[2] else res_h
coords.append(res)
return coords
@njit(fastmath=True)
def in_view(x1, y1, x2, y2, obstacles):
# Рейкаст, но с 1-ой линией, для проверки нахождения объекта в зоне видимости
phi = atan2(y2 - y1, x2 - x1)
cos_phi = cos(phi)
sin_phi = sin(phi)
distance = sqrt((x1 - x2) ** 2 + (y1 - y2) ** 2)
length = 0
while distance > 1:
ray_x = x1 + length * cos_phi
ray_y = y1 + length * sin_phi
distance = sqrt((ray_x - x2) ** 2 + (ray_y - y2) ** 2)
for ox, oy, map_w, map_h in obstacles:
if ox < ray_x < ox + map_w and oy < ray_y < oy + map_h:
return False
length += 1
return True