bezier curves do this nicely

simply set position to

X= cubic(p0.x,p1.x,p2.x,p3.x,variable('t'))

Y= cubic(p0.y,p1.y,p2.y,p3.y,variable('t'))

the p#'s are sprites which define the paths points. p0 would be the point the path starts at, p3 would be the one it ends at. the other 2 control the curvature of the path like so

as you can see t is a value which when changed moves the paths returned position along. it should be a number from 0 to 1. 0 meaning its at the complete beginning of the path, 1 meaning its at the absolute end. 0.5 would mean the center. imagine if you multiplied the number by 100 it would be the percent moved along the path. so 0.25 would be 25% and so on.

if you would like to move your object back and forth along the path at a certain speed simply add a small number like 0.01 to the t value. so it will take 100 frames to move it from p0 to point p3.

a value less than 0 or greater than 1 will simply move the object to a position that would exist if the curve were to continue at its current amount of deviation