For example, I have an object that follows mouse horizontally, its minimum position is 100 and the maximum is 200.
Within this range, it follows mouse linearly, meaning 1 unit of mouse position equals to 1 unit of object position.
Now, if the mouse is outside of the range (below 100, or above 200), I want it to start applying friction, so the object gracefully stops the further it is from range, for example:
Mouse position | Object position
200 200
220 205
240 209
260 212
280 215
300 217
320 218
340 219
360 220
380 220
400 220
...
I managed to implement it like this within mouse-move handler:
if (mousePosition > 200 || mousePosition < 100) {
delta = mousePosition - objectPosition;
objectPosition += delta * 0.25; // 0.25 if friction factor
}
But is there a better way? How to implement function outside of mouse-move handler:
getObjectPosition(mousePosition) {
return // ???
}
The question is language agnostic.
You can calculate your the object position as a piecewise function of the mouse position:
getObjectPosition(mousePosition) {
if(mousePosition < 100)
return 100 - friction(100 - mousePosition);
if(mousePosition > 200)
return 200 + friction(mousePosition - 200);
return mousePosition;
}
Where friction
is a function to calculate the "soft" function you want. A simple one would be:
friction(x) {
return 0.25*x;
}
which would reduce the object speed by 0.25 when its beyond the [100, 200] bounds. Your function seems to approach some kind of asymptote though. You can achieve it with, for example, a quadratic:
friction(x) {
M = 160;
x = min(x, M);
return x*(1 - x/(2*M));
}
Here the object will gradually slow down, and stop completely when the mouse is outside the [-60, 360] interval.