RapidGameFramework
Reusable Godot managers for data-driven small games
Loading...
Searching...
No Matches
physics_queries.gd
Go to the documentation of this file.
1extends RefCounted
2
3
6
7const CollisionPipeline = preload("res://scripts/systems/physicsEngine/collision_pipeline.gd")
8
9var collision_pipeline = CollisionPipeline.new()
10
11
12
13func point_query(bodies:Array, point:Vector2) -> Array:
14 var results = []
15 for body in bodies:
16 if _contains_point(body, point):
17 results.append(body.duplicate(true))
18 return results
19
20
21
22func aabb_query(bodies:Array, area:Rect2) -> Array:
23 var results = []
24 for body in bodies:
25 if collision_pipeline.get_aabb(body).intersects(area):
26 results.append(body.duplicate(true))
27 return results
28
29
30
31func raycast(bodies:Array, from:Vector2, to:Vector2) -> Dictionary:
32 var best := {}
33 var best_distance := INF
34 for body in bodies:
35 var hit = _ray_body(body, from, to)
36 if hit.is_empty():
37 continue
38 var distance = from.distance_to(hit.get("point", from))
39 if distance < best_distance:
40 best_distance = distance
41 best = hit
42 return best
43
44
45func _contains_point(body:Dictionary, point:Vector2) -> bool:
46 var shape = body.get("shape", {})
47 if str(shape.get("type", "aabb")) == "circle":
48 return point.distance_to(body.get("position", Vector2.ZERO)) <= float(shape.get("radius", 8.0))
49 return collision_pipeline.get_aabb(body).has_point(point)
50
51
52func _ray_body(body:Dictionary, from:Vector2, to:Vector2) -> Dictionary:
53 var shape = body.get("shape", {})
54 if str(shape.get("type", "aabb")) == "circle":
55 return _ray_circle(body, from, to)
56 return _ray_aabb(body, from, to)
57
58
59func _ray_circle(body:Dictionary, from:Vector2, to:Vector2) -> Dictionary:
60 var center = body.get("position", Vector2.ZERO)
61 var radius = float(body.get("shape", {}).get("radius", 8.0))
62 var direction = to - from
63 var length = direction.length()
64 if length <= 0.0001:
65 return {}
66 var dir = direction / length
67 var to_center = center - from
68 var projection = clamp(to_center.dot(dir), 0.0, length)
69 var closest = from + dir * projection
70 if closest.distance_to(center) <= radius:
71 return {"body": body.duplicate(true), "point": closest, "distance": from.distance_to(closest)}
72 return {}
73
74
75func _ray_aabb(body:Dictionary, from:Vector2, to:Vector2) -> Dictionary:
76 var rect = collision_pipeline.get_aabb(body)
77 var direction = to - from
78 var t_min := 0.0
79 var t_max := 1.0
80 for axis in ["x", "y"]:
81 var origin = from.x if axis == "x" else from.y
82 var dir = direction.x if axis == "x" else direction.y
83 var min_value = rect.position.x if axis == "x" else rect.position.y
84 var max_value = rect.end.x if axis == "x" else rect.end.y
85 if abs(dir) < 0.0001:
86 if origin < min_value or origin > max_value:
87 return {}
88 else:
89 var inv_dir = 1.0 / dir
90 var t1 = (min_value - origin) * inv_dir
91 var t2 = (max_value - origin) * inv_dir
92 if t1 > t2:
93 var temp = t1
94 t1 = t2
95 t2 = temp
96 t_min = max(t_min, t1)
97 t_max = min(t_max, t2)
98 if t_min > t_max:
99 return {}
100 var point = from + direction * t_min
101 return {"body": body.duplicate(true), "point": point, "distance": from.distance_to(point)}