Move point on curve with constans velocity (missing functions in library?)
krumza

Hi Gio, need some advice.

I make the object move along a curve (in my case, Bezier).

According to the curve formula 

//P = (1−t)3P1 + 3(1−t)2tP2 +3(1−t)t2P3 + t3P4

I set coordinates for x and y and then set is a position of my object, Something like:

obj.onUpdate = function(){
  t+=.005;
  x = ...//according formula
  y = ...//according formula
  obj.setRotation(Math.atan(dy/dx));//according formula
  obj.setPosition(x,y);
}

But I noticed that such a movement with linearly varying time has different speeds in different parts of the curve.

This is clearly visible if you attach several more objects and move them together like a train. The distance between segments changes on different sections of the curve.

I searched the Internet for solutions and it is logical of course that I found solutions for c++ and C# the essence of which is to divide the curve into points and then linear movement from point to point.

I see the solution as splitting the curve into a set of points and then using a bundle wade.sceneObject().moveTo() and wade.sceneObject.onMoveComplete() to move the object, but for some reason I don't like the solution (I didn't even do it)

I know that Gio is strong in mathematics and may have encountered similar things.

And of course it is worth noting that wade has no functions for working with curves. I think this is missing functionality

All 3 Comments
Gio

Hi krumza

It's true that wade has no functions to handle Bezier curves, however it does have Paths that sound exactly like what you need.

I think there is an easy and elegant solution to your problem: create a Path (which is, essentially, an array of "nodes") by splitting the curve into a set of points: for each point add a node to the path.

Then tell your SceneObject to follow the path:

var dt = 0.1; // how many seconds to go from one node to the next
var path = new Path();
myPoints.forEach(function(point) {
    path.addNode({position: point, duration: dt});
};
myObject.setPath(path);

This will give you linear motion, which is probably what you want, but you have more options if you want to add an additional parameter tweenType to each node; in that case you can add easing in and out of individual nodes with different polynomial functions.

Paths are especially useful for changing positions, but they can be used for lots of other things, to interpolate (or "tween" if you prefer) any properties of your objects and sprites.

In this particular case, you probably want to add rotation as well as position for each node.

krumza

It looks interesting, I'll try it.

But the question immediately arises - will I have flexibility with this approach if I

1) change the curve parameters

2) bind the curves to the tiles

Gio

With that approach you can change the curve all you like, the idea is that you sample it and create linear segments.

I was just answering your question regarding an alternative to a long chain of moveTo and onMoveComplete. But for the record, I don't think that's the best approach to solving your problem. Your approach with an onUpdate function is the right idea, but the maths isn't quite that straightforward.

In essence, the Bezier curve has a parameter t that you change from 0 to 1 to get sets of x and y coordinates. The problem is that equal changes of t result in different segment lengths, depending on the values of t itself. Instead you want a different parameter T that say, you could change by 0.1 and always span a segment that's 10% the length of the curve, regardless of where you are on the curve.

The maths to change the Bezier equation to use T rather than t is quite involved, to apply the constant distance constraint you'd have to integrate the square root of the derivatives of the Bezier.

Luckily though, this is a classic problem and there is a simple (though approximate) solution, you can find the details in this stackexchange answer.

Post a reply
Add Attachment
Submit Reply
Login to Reply