Accelerate and slow down a camera move

Hi folks,
I have a 2d scene, and do camera moves between two given points by simply defining N equal intermediate steps along the line formed by the start and stop point.
I’d like to accelerate at the beginning and slow down at the end. Do you have any suggestions to do that smartly?
Cheers,
Martin

Have an acceleration vector or variable and add it to the velocity until you reach your maximum velocity. Then (velocity/acceleration) ticks before you reach the other point, subtract that acceleration from the velocity until you reach 0.

Heh, I was just working on almost exactly the same problem. In my game one can move the camera with the keys but I want the motion to accelerate at first. (Think StarCraft RTS camera panning control)

Here’s how you calculate the distance with initial acceleration and then constant velocity movement. I’ll leave the deceleration portion as an exercise for the reader.

From physics class you learn:
distance = velocity * time
distance = 0.5 * acceleration * time^2

Thus if you know at what point your camera was when you first started panning, then this is how you calculate the distance that the camera should have moved:


elapsed_sec = (System.currentTimeMillis - start_ms) / 1000.0

velocity = 7.0  // units per sec
accel = 9.0  // units per sec^2

accel_dur_sec = 1.0  // acceleration happens for the first second, then speed is constant after that

distance = 0.0
if (elapsed_sec < accel_dur_sec) {
    distance = 0.5 * accel * elapsed_sec * elapsed_sec
} else {
    distance = 0.5 * accel * accel_dur_sec * accel_dur_sec + velocity * (elapsed_sec - accel_dur_sec)
}

Or you can do it in stepwise intervals as ra4king described.

That works too :slight_smile:

Hi,

Thanks for these suggestions. One thing I forgot to tell: I want to control the LENGTH of each animation. Up to now I check the frame rate before starting any animation, to determine the number of necessary key points required to have the choosen duration. Unless I misunderstood your suggestion, it seems to me that your solutions requires little thinking to determine acceleration and other parameters to control the number of steps.

I was thinking about using a function to shifts linear steps:

(1) compute the linear interpolation of the n intermediate steps. First and last point make distance D.
(2) convert each point to polar, to have a distance information from start.
(3) then each point Pi should be at distance= D*i/n from start.

(4) For this next step, the best is to normalize in [0;1], so consider distance=i/n. We will update each polar point with:
P.radius = f(P.radius)
I thus need a function y=f(x) that gives y=0 for x=0 and y=1 for x=1, and that let me “stretch” the animation timing easily:
f(x)=x^2 makes a simple accelerating move, x^3,4,5 will be more “sharp”: slower at the beginning and faster at the end.
f(x)=-(x-1)^2+1 makes the contrary acceleration: fast at the beginning, slow at the end. One must have an even pow value.

so I better need a normalized sigmoïd function. I will tell you if I find a good candidate for this method :slight_smile:

It is a little mangled, but allows to customize speed variation easily! Maybe there are some other more straightforward methods.

Cheers,
Martin

Edit: This was probably not helpful at all after I read the last post by martin :slight_smile:

Here is a very simple filter for smooth movement. Just set the factor between 0 and 1 and call the update() method with the target position. For 2D, just use two DoubleSmoothers, one for x and the other for y. You can also use it for any smooth transition like zoom, angle etc.
A smaller factor gives a slower movement until you reach 0 (no movement at all).


public class DoubleSmoother {

	private double factor;
	private double current;

	public DoubleSmoother(double factor, double start) {
		this.factor = factor;
		this.current = start;
	}

	public DoubleSmoother(double factor) {
		this(factor, 0.0);
	}

	public double getValue() {
		return current;
	}

	public double update(double value) {
		current = factor * value + (1.0 - factor) * current;
		return current;
	}
	
	public void setValue(double value) {
		current = value;
	}

}



If you know some filter theory, then it might help you that this is simply a single pole, linear, discrete filter.

Thanks for the piece of code!

After some more thought, I came out with the following idea: a “standard” sigmoïd method works, but it is not easy to control tune it. Actually I just would like to build a function that looks like a smoothed stair:

1 /- slow stop
| /-/
0-/ 1 slow start

satisfying f(0)=0, f(0.5)=0.5 and f(1)=1, and any other constraint letting me say “at T I want the cam to have done distance D”. Finally, it seems the best is to “build” the function using an interpolation (I will use bernstein, that works well), where each keypoint represent a D=f(T) constraint. One can really “model” the camera behaviour with details.

Cheers,
Martin