+1 vote

I'm trying to work about a way of moving a sprite along a Path2D based on a mouse click, So if the player clicks at a point on the screen at say, 800px on the X axis, the sprite would move to the corresponding (or closest) point on the Path2D.

Basically trying to get an adventure game type of thing going, where the player can only move along a fairly basic path.

Is this even possible? If not, what would be a better Godot approach?

Thanks in advance

asked May 17 in Engine by bl-rd (16 points)

Could you be a little more specific?
When you say move to the closet Path2D, you mean move to the predefined path or make their own path.

Sorry - I mean on a predefined Path2D.

So for example a scene would have a simple, single Path2D with fixed points that player sprite can navigate along. When the player clicks on the scene, the sprite moves to the closest baked point on the Path2D.

Does that make sense?

Yeah Ok.
Lemme come up with something.

1 Answer

0 votes
Best answer

Ok how about this.
After making your path with the mentioned Path2D node, create a navigation2D node and 2 NavigationPolygons as a child of that. They will act as walls to surround the Path2D node, but don't let the path inside of the polygons. The covered parts are where the navigation avoids walking into. So if you start from inside the navigation polygons, then you should end up in the closest uncovered parts. In this case, the surrounded path. Just be sure to cover areas outside of your view too or else your navigation may walk outside of the screen.

That should be enough for node setup. Now to.. Oh wait! Almost forgot. We will also want a second Path2D node with a PathFollow2D node as a child. Is will be needed when-

GDScripting

The code will be inside your player node/scene. We will need a reference to the Navigation 2D, the second Path2D, and it's PathFollow2D to start with.

Now after we get those important stuff, we will now create code to get a path. From your player's current position, to a point where the mouse has clicked. We will do that in a function when the mouse is clicked.

func _input(event):
    if event is InputEventMouseButton:
        if event.pressed:
            #nav is reference to Navigation2D node.
            var path_points = nav.get_simple_path(position, event.position)
            #we will now create a Curve2D resource with these points.
            var curve = Curve2D.new()
            for point in path_points:
                curve.add_point(point)
            #and now we put the curve into the Path2D node(second one).
            path.curve = curve
            path_follow.offset = 0
            following_path = true

Now that the path is in the path node, we can now follow it to its end with the pathfollow2D node. Code for this will be run continuously; so we will put it in either _process or _physics_process.

func _process(delta):
    if following_path:
        path_follow.offset += 50*delta #This number is the player's speed. Which you can change.
        if path_follow.unit_offset >= 1:
            path_follow.unit_offset = 1
            following_path = false

        global_transform = path_follow.global_transform

And that should be all! BTW I made this all up without Godot on me right now so if there is anything wrong, let me know.

I hope all this typing was not all in vain. I'm doing it on a phone!

answered 6 days ago by SIsilicon (937 points)
selected 6 days ago by bl-rd

Wow - thanks! Excellent commitment using your phone :)

So it kind of works. I may not have set it up as you imagined. Here's the structure:

Scene structure
And heres the code (on the sprite):

extends Sprite

var following_path = false
var path_follow
export (int) var SPEED

func _process(delta):
    path_follow = get_parent().get_node("Path2D2/PathFollow2D")
    if following_path:
        path_follow.offset += SPEED * delta
        if path_follow.unit_offset >= 1:
            path_follow.unit_offset = 1
            following_path = false

        global_transform = path_follow.global_transform


func _input(event):
    if event is InputEventMouseButton:
        if event.pressed:
            var path_points = get_parent().get_node('Navigation2D').get_simple_path(position, event.position)
            var curve = Curve2D.new()
            for point in path_points:
                curve.add_point(point);
            get_parent().get_node("Path2D2").curve = curve
            path_follow.offset = 0
            following_path = true

And the result:

Scene gif

As you can see it works on the first one, but then resets back to the beginning. On the second one it it gets to the right click location, but seems to ignore the third point on the Path2d.

That second one works exactly as how it should. You see it's not really following the path, but the area around the path. If you want it any closer, then you should have the navigationpolygon closer to the path.

And I also know why it resets to the beginning. Your pathfollow's loop option is enabled. Once unit_offset becomes >= 1 then it would *loop* back.

And I bet you don't want that scale to change. In that it case, instead of doing-

global_transform = path_follow.global_transform

Instead do-

position = path_follow.position
rotation = path_follow.rotation

Don't forget to vote n' select ;)

Nice. It's exactly the kind of effect I'm trying to achieve. Thanks a lot!

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.