Following Path2D points with loop - backwards tween moving problem.

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By michal14

I would like to create board like in monopoly game.

I created Path2D with 40 closed points, and I added PathFollow2D as child. Problem is, because eg. If I’m on 35 field and I would like move to 5 field, PathFolllow2D is backwards instead go forward.

Video: https://streamable.com/0axm8d

Here is my code:

extends Node2D

@onready var path_2d := $Path2D as Path2D
@onready var path_follow_2d := $Path2D/PathFollow2D as PathFollow2D

var current_field = 0

func move(amount: int):
	if (current_field + amount) < 39:
		current_field += amount
	else:
		current_field = abs(40 - (current_field + amount))
		
	print("Field: %s" % current_field)
	
	var offset = path_2d.curve.get_closest_offset(path_2d.curve.get_point_position(current_field))
	var tween = get_tree().create_tween()
	tween.tween_property(path_follow_2d, "progress", offset, 1.2).set_trans(Tween.TRANS_SINE)

How can I fix this?

Is the loop property set to true on your PathFollow2D?

jgodfrey | 2023-01-07 15:38

Yes. I have loop property with value true.

michal14 | 2023-01-07 15:39

Oh, I see your code is intentionally preventing a “wrap” around the end point. Assuming you do have loop=true (as mentioned above), what happens if you change your move() method to simply add the passed amount without modifying the result?

I think I’d expect that to behave as you intend, though maybe that causes you other problems?

jgodfrey | 2023-01-07 15:41

Untested, but I’d try something like this:

func move(amount: int):
    current_field += amount

    print("Field: %s" % current_field)

    var offset = path_2d.curve.get_closest_offset(path_2d.curve.get_point_position(current_field))
    var tween = get_tree().create_tween()
    tween.tween_property(path_follow_2d, "progress", offset, 1.2).set_trans(Tween.TRANS_SINE)
    current_field %= 40

That should allow values > 40 for the tween, which (I think) should wrap as expected. Once that’s done, current_field is again reduced to a value < 40…

jgodfrey | 2023-01-07 15:51

I have error:

E 0:00:12:0343   _on_roll_dice_pressed: Index p_index = 45 is out of bounds (points.size() = 41).

Because I have only 40 points.

michal14 | 2023-01-07 15:53

Is that error based on my first suggestion (to just keep adding amount) or on the code I posted above - which should ensure the value is < 40? If you haven’t tried something like the above code, give it a try.

jgodfrey | 2023-01-07 15:56

When I just keep amount i have error like on above, because I have only 39 indexes on path2d.

michal14 | 2023-01-07 15:59

Sorry - It’s not clear whether you’ve tried the modified version of move() I posted above? And, I’ll say that I HAVE NOT tried it…

jgodfrey | 2023-01-07 16:02

Yes, I tested your version and I have this error:

_on_roll_dice_pressed: Index p_index = 45 is out of bounds (points.size() = 41).

michal14 | 2023-01-07 16:04

It should be pretty easy to get the result you want. Is the project available anywhere for inspection?

jgodfrey | 2023-01-07 16:05

Yes, here:
Dropbox - Business+.zip - Simplify your life
Godot 4 beta 10

michal14 | 2023-01-07 16:06

:bust_in_silhouette: Reply From: jgodfrey

OK, based on the linked project, here’s what I came up with. While I think it works correctly, it seems like it could/should be simpler than this. And, this code deals with a few edge cases that could probably be factored away with some thought. Anyway, hopefully this does what you want…

func move(amount: int):
	var time_per_cell = 0.3
	var time = time_per_cell * amount
	var point_count = path_2d.curve.point_count
	var tween = get_tree().create_tween()

	current_field += amount
	if current_field >= point_count:
		current_field %= point_count
		current_field += 1
	
	var curr_offset = path_follow_2d.progress
	
	var offset = path_2d.curve.get_closest_offset(path_2d.curve.get_point_position(current_field))
	
	if offset < curr_offset:
		offset += path_2d.curve.get_baked_length()
	
	tween.tween_property(path_follow_2d, "progress", offset, time).set_trans(Tween.TRANS_SINE)
	await tween.finished
	
	current_field %= point_count
	path_follow_2d.progress = fmod(path_follow_2d.progress, path_2d.curve.get_baked_length())

Oh, also I normalized the speed of movement with that time_per_cell value, that dictates how long it should take to move between 2 consecutive points in your path.

jgodfrey | 2023-01-07 21:10

Note, I just made one small edit to the above posted code… :frowning:

jgodfrey | 2023-01-07 21:16

Thank you. It works very well. Can you give me your paypal or other method of showing gratitude for your help?

michal14 | 2023-01-07 22:32

Glad it works - and happy to help. No need for anything more than the “thanks”.

jgodfrey | 2023-01-07 22:40

Then thank you very much.

michal14 | 2023-01-07 23:36