In a previous post, I mentioned looking for a polynomial for an application. I am working on an application that involves clicking or dragging tiles around. Once you release the tile, I want it to snap to where it’s supposed to be.
The easiest way to do this is to just warp it to where it’s supposed to go. This isn’t very visually pleasing. The next best thing is to set up a time-interval on which it moves into place. Then, linearly interpolate from where it is to where it’s going (here with normalized to range between zero and one):
That’s much better than just warping, but it doesn’t have any sort of fade-in or fade-out. It instantaneously has its maximum velocity and then instantaneously stops at the end.
Typically, then one uses a cubic spline to scale the value before interpolating to get a speed up in the beginning and then slow down in the end.
I might like to decelerate faster than I accelerate though so I might employ a fancier (higher-order) polynomial like:
But, in this case, I wanted the tile to overshoot the target a bit and then nestle/wiggle into place. So, I experimented with a bunch of different polynomials. I was having real trouble getting them to behave in a way that felt right. So, I went back to the physics of it.
What I wanted was pretty similar to damped spring motion. Imagine you’ve tied a heavy weight to a spring and suspended it all in a jar of oil. If you perturb the weight, it will bounce up and down but
each bounce is closer to the equilibrium point than the previous bounce. (Actually, it’s more complicated than that. If the spring is too weak or the oil too viscous, the weight will just slowly return to the equilibrium point without ever going past it. That’s called
overdamped harmonic oscillation. What I want is called
underdamped harmonic oscillation and that’s all I will concern myself with here.) The equation for this motion is:
To get it to wiggle an appropriate amount, I was using and effectively making the cosine into a sine.
This is all well and good, but to really scale my t, I need this to start at zero and approach one. So, I was really using:
Well, now it starts zig-zagging on the way to its destination. It already starts cutting back long before it makes it to where it’s going. I needed to get close to the destination much sooner. So, I jiggered the term:
This looks terrible though. I hit the destination is less than a tenth of a second and then not again until about half a second. The reason for this is that the oscillations happen at a fixed rate. never changes and moves steadily along so that keeps the same frequency throughout my interval. So, I jiggered the going into the sine function to make my oscillations start out slowly and really speed up toward the end.
This is much better, but it still didn’t give the feeling of settling in because the second oscillation was almost as high as the first. I could up the value of and get somewhere. But, I wanted it to be even more dramatic. So, I changed the in the exponent to (and used a slightly higher : was 3 and is now 4):
This was pretty decent, but I felt the initial attack was a bit strong. So, I dropped down the exponent on my base curve from 4 to 2:
This is pretty nice. It looks pretty natural (despite making an entire mess out of damped harmonic motion). It doesn’t ease in at all though so I might still need to replace the with something of a higher order. But, I might not mind the tile achieving instant velocity. It gives it that
I’m really supposed to be over there sort of urgency.