0
\$\begingroup\$

So i am trying to make a rope between player and where raycast hit in 2d godot.I have rope piece instance with rigibody/staticbody and pinjoint. So what i am doing is spawning enough pieces as a child of a gameobject between player and collision point of ray and the rope is spawning good enough but rotation isnt working. I have tried everything but its just not working.

Here is my horrendous code

elif Input.is_action_just_pressed("shoot") and ray.is_colliding():
    
    $".".gravity_scale=0
    var positionPlayer=$".".position
    
    
    var total = ceil(positionPlayer.distance_to(ray.get_collision_point()) / gap)
    
    var rays=ray.get_collision_point()
    
    var playerPos=$".".position
    

    isSpawned=true
    for n in total:
        
        if(firstTime):
            
            var pos=ray.get_collision_point()
            
            
            pos.y+=25
            pos.x-=35   
            $"../ropewa".position=pos
            
            obj1=ray.get_collider()
            var rope=ropePiece.instance()
            $"../ropewa".add_child(rope)
            
                
            
            
        
            obj2=rope.get_node("PinJoint2D")
            obj2.node_a=obj1.get_path()
            obj2.node_b=rope.get_path()
            obj1=rope
            firstTime=false
            
        if(n==total-1):


            var rope=ropePiece.instance()
            $"../ropewa".add_child(rope)
            
            rope.position=obj1.position
            rope.position.y+=add
            
            
            obj2=rope.get_node("PinJoint2D")
            obj2.node_a=obj1.get_path()
            obj2.node_b=rope.get_path()
            $".".get_node("PinJoint2D").node_b=rope.get_path()
        





        else:
            if(firstTime==false):
                var rope=ropePiece.instance()
                $"../ropewa".add_child(rope)
                
                rope.position=obj1.position
                
                rope.position.y+=add

            
                obj2=rope.get_node("PinJoint2D")
                obj2.node_a=obj1.get_path()
                obj2.node_b=rope.get_path()
                obj1=rope   

what I am doing is spawning a rope piece and joining the old rope piece and new rope piece. ropewa is the gameobject with all the child inside of it.$"." is the main player. My solution so far Game1 game2

\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

You have the position the raycast hit:

ray.get_collision_point()

That position is in global coordinates. Meanwhile the position of the player is not global (it is relative to its parent). Use global_position instead.

Let us do this:

var rope_start := ray.get_collision_point()
var rope_end := global_position

And we can figure out distance and direction:

var rope_length := rope_start.distance_to(rope_end)
var rope_direction := rope.start.direction_to(rope_end)

Define a size for the rope piece. I'll go with this (tweak it if it is wrong):

var rope_piece_length := 25.0 # gap

With that length and the direction we can have a vector that represents the step from once piece to the next:

var rope_piece_step := rope_piece_direction * rope_piece_length

Next figure out how many we need:

var rope_piece_count := int(ceil(rope_length / rope_piece_length))

Then we can iterate and figure out the position of each piece:

for n in rope_piece_count:
    var rope_piece_position := rope_start + rope_piece_step * n

Since you need to connect the pieces, you want to keep track of the prior piece you created to connect to it. In fact, since the first thing you will connect to is what the raycast collided with, we can initialize with that and avoid the first time check:

var rope_parent:Node = $"../ropewa"
var fixed:PhysicsBody2D = ray.get_collider()
for n in rope_segment_count:
    var rope_piece_position := rope_start + rope_piece_step * n
    var rope:PhysicsBody2D = ropePiece.instance()
    rope_parent.add_child(rope)
    rope.global_position = rope_piece_position
    var pin_joint := rope.get_node("PinJoint2D") as PinJoint2D
    pin_joint.node_a = fixed.get_path()
    pin_joint.node_b = rope.get_path()
    fixed = rope

I want to encourage you to compare my code with yours and see that it makes sense.

At the end (after the loop) you want to connect the last piece:

$PinJoint2D.node_b = fixed.get_path()

On the $ syntax

There is no need to do this: $".", because it is the same as self, but with overhead. So instead of $".".position you can write self.position.

In fact, usually you don't need self. If you are accessing one of the built-in properties feel free to simply use its name (e.g. position as opposed to self.position). If you are accessing a custom property that was created with setget, then it depends (using self will trigger the setget, and not using it will bypass it).

Also $".".get_node("PinJoint2D") is equivalent to $"./PinJoint2D"which is equivalent to $"PinJoint2D" which is equivalent to $PinJoint2D which is how I wrote it above.

\$\endgroup\$
1
  • \$\begingroup\$ Thank you so much. I am new to godot. It works amazingly. God bless you \$\endgroup\$ Commented Dec 21, 2022 at 22:25

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.