Skip to content

Commit a8de617

Browse files
committed
Add example for attaching multiple ropes to a RigidBody
Also updates the rigidbody_rope_attachment example scene. Related to #34
1 parent 7de0189 commit a8de617

File tree

3 files changed

+164
-24
lines changed

3 files changed

+164
-24
lines changed

demo/rope_examples/rigidbody_rope_attachment.tscn

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,27 @@ horizontal_alignment = 1
4242

4343
[node name="Label" type="Label" parent="."]
4444
offset_left = 10.0
45-
offset_top = 451.0
46-
offset_right = 852.0
47-
offset_bottom = 630.0
48-
text = "Basic example on how to attach a RigidBody to a rope and enabling corresponding physics reactions.
49-
50-
A PinJoint2D fixates the RigidBody to the rope.
45+
offset_top = 381.0
46+
offset_right = 1186.0
47+
offset_bottom = 638.0
48+
text = "A PinJoint2D fixates the RigidBody to the rope.
49+
As it only works on two physics bodies, a CharacterBody (rope_end) is used as proxy for the location on the rope.
5150
The softness property on the PointJoint2D can be tuned to make the RigidBodies less erratic on collisions.
5251
53-
A RopeInteraction uses the RigidBody to control the rope and updates the PinJoint2D respectively.
54-
For this purpose, the RopeInteraction makes use of the input_override_node property."
52+
A RopeInteraction handles the mutual interaction between the RigidBody and the rope.
53+
It snaps the rope to the position indicated by the attachment_marker node and updates the rope_end+PinJoint2D to constrain the RigidBody to the rope.
54+
To specifically target the marker, the RopeInteraction makes use of the input_override_node property.
55+
56+
The PinJoint2D, the rope_end and the attachment_marker nodes should be aligned initially, otherwise it may lead to undesired behavior.
57+
The disable_in_editor property of RopeInteraction is useful to prevent accidantelly messing up the layout."
58+
59+
[node name="Label2" type="Label" parent="."]
60+
offset_left = 10.0
61+
offset_top = 8.0
62+
offset_right = 1146.0
63+
offset_bottom = 109.0
64+
text = "Basic example on how to attach a RigidBody to a rope and enabling corresponding physics reactions.
65+
66+
Keep in mind that Godot's internal physics and the rope simulation of this plugin are completely different approaches.
67+
Combining them is a hack that will never produce perfect results and is not particularily intuitive."
68+
autowrap_mode = 3
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
[gd_scene load_steps=7 format=3 uid="uid://cioc6wtbs3ubf"]
2+
3+
[ext_resource type="Script" uid="uid://b2shq2gjd4fvt" path="res://addons/ropesim/Rope.gd" id="1_mk4gc"]
4+
[ext_resource type="Script" uid="uid://y8nntt6dh711" path="res://rope_examples/scripts/character_body_2d.gd" id="1_ww34l"]
5+
[ext_resource type="Script" uid="uid://dvxegqp0cf77n" path="res://addons/ropesim/RopeInteraction.gd" id="2_ww34l"]
6+
[ext_resource type="Texture2D" uid="uid://criwv6nuivcxy" path="res://rope_examples/icon.svg" id="3_ovf25"]
7+
8+
[sub_resource type="PhysicsMaterial" id="PhysicsMaterial_nwm6u"]
9+
10+
[sub_resource type="RectangleShape2D" id="RectangleShape2D_3g7xa"]
11+
size = Vector2(64, 64)
12+
13+
[node name="rope_with_body" type="Node2D"]
14+
position = Vector2(479, 16)
15+
16+
[node name="left_rope_mover" type="CharacterBody2D" parent="."]
17+
position = Vector2(-176, 62)
18+
motion_mode = 1
19+
script = ExtResource("1_ww34l")
20+
21+
[node name="Rope" type="Node2D" parent="left_rope_mover"]
22+
script = ExtResource("1_mk4gc")
23+
num_segments = 15
24+
rope_length = 250.0
25+
gravity = 61.765
26+
num_constraint_iterations = 20
27+
28+
[node name="RopeInteraction" type="Node" parent="left_rope_mover/Rope" node_paths=PackedStringArray("target_node", "input_node_override", "rope")]
29+
script = ExtResource("2_ww34l")
30+
disable_in_editor = true
31+
position_update_mode = 0
32+
target_node = NodePath("../../../hanging_rigidbody/attach_marker/rope_end")
33+
input_node_override = NodePath("../../../hanging_rigidbody/attach_marker")
34+
rope = NodePath("..")
35+
36+
[node name="Label" type="Label" parent="left_rope_mover"]
37+
offset_left = -24.0
38+
offset_top = -34.0
39+
offset_right = 23.0
40+
offset_bottom = -11.0
41+
text = "WSAD"
42+
43+
[node name="right_rope_mover" type="CharacterBody2D" parent="."]
44+
position = Vector2(185, 80)
45+
motion_mode = 1
46+
script = ExtResource("1_ww34l")
47+
use_arrow_keys = true
48+
49+
[node name="Rope2" type="Node2D" parent="right_rope_mover"]
50+
script = ExtResource("1_mk4gc")
51+
num_segments = 15
52+
rope_length = 250.0
53+
gravity = 61.765
54+
num_constraint_iterations = 20
55+
56+
[node name="RopeInteraction" type="Node" parent="right_rope_mover/Rope2" node_paths=PackedStringArray("target_node", "input_node_override", "rope")]
57+
script = ExtResource("2_ww34l")
58+
disable_in_editor = true
59+
position_update_mode = 0
60+
target_node = NodePath("../../../hanging_rigidbody/attach_marker2/rope_end2")
61+
input_node_override = NodePath("../../../hanging_rigidbody/attach_marker2")
62+
rope = NodePath("..")
63+
64+
[node name="Label" type="Label" parent="right_rope_mover"]
65+
offset_left = -24.0
66+
offset_top = -34.0
67+
offset_right = 23.0
68+
offset_bottom = -11.0
69+
text = "Arrow keys"
70+
71+
[node name="hanging_rigidbody" type="RigidBody2D" parent="."]
72+
position = Vector2(-75, 156)
73+
mass = 20.091
74+
physics_material_override = SubResource("PhysicsMaterial_nwm6u")
75+
metadata/_edit_group_ = true
76+
77+
[node name="attach_marker" type="Marker2D" parent="hanging_rigidbody"]
78+
position = Vector2(-19, 0)
79+
metadata/_edit_group_ = true
80+
81+
[node name="rope_end" type="CharacterBody2D" parent="hanging_rigidbody/attach_marker"]
82+
collision_layer = 0
83+
collision_mask = 0
84+
motion_mode = 1
85+
86+
[node name="PinJoint2D" type="PinJoint2D" parent="hanging_rigidbody/attach_marker/rope_end"]
87+
node_a = NodePath("../../..")
88+
node_b = NodePath("..")
89+
softness = 0.05
90+
91+
[node name="attach_marker2" type="Marker2D" parent="hanging_rigidbody"]
92+
position = Vector2(22, 0)
93+
metadata/_edit_group_ = true
94+
95+
[node name="rope_end2" type="CharacterBody2D" parent="hanging_rigidbody/attach_marker2"]
96+
collision_layer = 0
97+
collision_mask = 0
98+
motion_mode = 1
99+
100+
[node name="PinJoint2D2" type="PinJoint2D" parent="hanging_rigidbody/attach_marker2/rope_end2"]
101+
node_a = NodePath("../../..")
102+
node_b = NodePath("..")
103+
softness = 0.05
104+
105+
[node name="CollisionShape2D" type="CollisionShape2D" parent="hanging_rigidbody"]
106+
shape = SubResource("RectangleShape2D_3g7xa")
107+
108+
[node name="Icon" type="Sprite2D" parent="hanging_rigidbody"]
109+
scale = Vector2(0.5, 0.5)
110+
texture = ExtResource("3_ovf25")
111+
112+
[node name="Label" type="Label" parent="."]
113+
offset_left = -467.0
114+
offset_top = 466.0
115+
offset_right = 709.0
116+
offset_bottom = 619.0
117+
text = "Very similar setup to the \"rigidbody_rope_attachment\" example but with two ropes attached simultaneously.
118+
The same principles apply as before.
119+
120+
As before, attaching Rigidbodies to ropes is a hack and will be tricky to make look right.
121+
For example, visible gaps will appear if both ropes are pulled away too far from each other.
122+
Additionally, ropes are not processed simultaneously. One rope will always be updated earlier, which can cause execution order related effects."

demo/rope_examples/scripts/rope_with_rigidbody.tscn

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -19,26 +19,16 @@ rope_length = 250.0
1919
gravity = 75.0
2020
num_constraint_iterations = 20
2121

22-
[node name="RopeInteraction" type="Node" parent="." node_paths=PackedStringArray("target_node", "input_node_override", "rope")]
22+
[node name="RopeInteraction" type="Node" parent="Rope" node_paths=PackedStringArray("target_node", "input_node_override", "rope")]
2323
script = ExtResource("2_1yts0")
24+
disable_in_editor = true
2425
position_update_mode = 0
25-
target_node = NodePath("../pin_point")
26-
input_node_override = NodePath("../hanging_rigidbody")
27-
rope = NodePath("../Rope")
28-
29-
[node name="pin_point" type="CharacterBody2D" parent="."]
30-
position = Vector2(0, 250)
31-
collision_layer = 0
32-
collision_mask = 0
33-
motion_mode = 1
34-
35-
[node name="PinJoint2D" type="PinJoint2D" parent="pin_point"]
36-
node_a = NodePath("../../hanging_rigidbody")
37-
node_b = NodePath("..")
38-
softness = 0.05
26+
target_node = NodePath("../../hanging_rigidbody/attachment_marker/rope_end")
27+
input_node_override = NodePath("../../hanging_rigidbody/attachment_marker")
28+
rope = NodePath("..")
3929

4030
[node name="hanging_rigidbody" type="RigidBody2D" parent="."]
41-
position = Vector2(0, 250)
31+
position = Vector2(0, 281)
4232
mass = 5.0
4333
physics_material_override = SubResource("PhysicsMaterial_nwm6u")
4434
metadata/_edit_group_ = true
@@ -49,3 +39,17 @@ shape = SubResource("RectangleShape2D_3g7xa")
4939
[node name="Icon" type="Sprite2D" parent="hanging_rigidbody"]
5040
scale = Vector2(0.5, 0.5)
5141
texture = ExtResource("3_uwcl5")
42+
43+
[node name="attachment_marker" type="Marker2D" parent="hanging_rigidbody"]
44+
position = Vector2(0, -31)
45+
metadata/_edit_group_ = true
46+
47+
[node name="rope_end" type="CharacterBody2D" parent="hanging_rigidbody/attachment_marker"]
48+
collision_layer = 0
49+
collision_mask = 0
50+
motion_mode = 1
51+
52+
[node name="PinJoint2D" type="PinJoint2D" parent="hanging_rigidbody/attachment_marker/rope_end"]
53+
node_a = NodePath("../../..")
54+
node_b = NodePath("..")
55+
softness = 0.05

0 commit comments

Comments
 (0)