9func resolve_collisions(bodies:Dictionary, contacts:Array, positional_percent:float = 0.8, slop:float = 0.01) -> Dictionary:
10 var next = bodies.duplicate(true)
11 for contact
in contacts:
12 var a_id = str(contact.get(
"a", {}).get(
"id",
""))
13 var b_id = str(contact.get(
"b", {}).get(
"id",
""))
14 if not next.has(a_id)
or not next.has(b_id):
16 var a = next[a_id].duplicate(true)
17 var b = next[b_id].duplicate(true)
18 var normal = contact.get(
"normal", Vector2.RIGHT)
19 var penetration =
float(contact.get(
"penetration", 0.0))
20 var inv_a =
float(a.get(
"inv_mass", 0.0))
21 var inv_b =
float(b.get(
"inv_mass", 0.0))
22 var inv_total = inv_a + inv_b
25 var relative_velocity = b.get(
"velocity", Vector2.ZERO) - a.get(
"velocity", Vector2.ZERO)
26 var velocity_along_normal = relative_velocity.dot(normal)
27 if velocity_along_normal < 0.0:
28 var restitution = min(
float(a.get(
"restitution", 0.1)),
float(b.get(
"restitution", 0.1)))
29 var impulse_magnitude = -(1.0 + restitution) * velocity_along_normal / inv_total
30 var impulse = normal * impulse_magnitude
31 a[
"velocity"] = a.get(
"velocity", Vector2.ZERO) - impulse * inv_a
32 b[
"velocity"] = b.get(
"velocity", Vector2.ZERO) + impulse * inv_b
33 var correction = normal * max(penetration - slop, 0.0) / inv_total * positional_percent
34 a[
"position"] = a.get(
"position", Vector2.ZERO) - correction * inv_a
35 b[
"position"] = b.get(
"position", Vector2.ZERO) + correction * inv_b
42func solve_distance_constraint(bodies:Dictionary, constraint:Dictionary) -> Dictionary:
43 var next = bodies.duplicate(true)
44 var a_id = str(constraint.get(
"a",
""))
45 var b_id = str(constraint.get(
"b",
""))
46 if not next.has(a_id)
or not next.has(b_id):
48 var a = next[a_id].duplicate(true)
49 var b = next[b_id].duplicate(true)
50 var delta = b.get(
"position", Vector2.ZERO) - a.get(
"position", Vector2.ZERO)
51 var distance = delta.length()
52 if distance <= 0.0001:
54 var target =
float(constraint.get(
"distance", distance))
55 var stiffness = clamp(
float(constraint.get(
"stiffness", 1.0)), 0.0, 1.0)
56 var normal = delta / distance
57 var inv_a =
float(a.get(
"inv_mass", 0.0))
58 var inv_b =
float(b.get(
"inv_mass", 0.0))
59 var inv_total = inv_a + inv_b
62 var correction = normal * (distance - target) * stiffness / inv_total
63 a[
"position"] = a.get(
"position", Vector2.ZERO) + correction * inv_a
64 b[
"position"] = b.get(
"position", Vector2.ZERO) - correction * inv_b
71func solve_constraints(bodies:Dictionary, constraints:Array, iterations:int = 1) -> Dictionary:
72 var next = bodies.duplicate(true)
73 for _i
in range(max(1, iterations)):
74 for constraint
in constraints:
75 if str(constraint.get(
"type",
"distance")) ==
"distance":
76 next = solve_distance_constraint(next, constraint)
float
Resolve contacts with impulse response and positional correction.