You could also make this even better by smoothing the transition with a math.sin(p)
How would you do that?
You'd need to make a modification to this code:
if (p > 1) then
p = 1
startTransition = false
end
and to this code:
camX = startX + ((destX - startX) * p)
camY = startY + ((destY - startY) * p)
But first lets focus on the conceptual stuff.
What is it we want to do? (in exacting detail..)
We want to move the camera from the current coordinates, to a new set of coordinates, with a smoothed motion. At the beginning of the transition, the camera moves slowly, accelerating. Halfway through the transition the camera has reached its maximum speed. At the end of the transition the camera is slowing down, until it smoothly comes to a stop at the very end.
How do we implement that?
We can obtain the smooth motion by using a sine or cosine.
Consider this graph:

The good old up and down wavy motion.
Ok, here's what we're gonna do; the X-axis on this graph shall represent p, which is linearly increasing at a rate of 0.02 every game cycle, with there being 60 game cycles per second.
The y-axis shall represent a proportion of how much distance we move per cycle.
So to get a smooth transition, we start by hardly moving at all, then halfway through we're moving quite fast, then right at the end we slow down again to 0.
So it looks like the sine wave will work best for this:

It will work best because it starts at 0 on the vertical axis (no movement), then increases rapidly (accelerating), reaching its maximum speed at x = (math.pi() / 2), then slowing down, until at x = (math.pi()) it comes to a stop.
It perfectly describes the motion that we want for our transitions. We just need to find a way to marry it to the amount of movement we want on any given transition.
In order to do that, we first need to know how many steps there will be in total. Since we're proceeding at a rate of 0.02, and we need to reach the value of pi (3.14159265...), it will take us 157 game cycles to reach pi according to my calculator.
It's going to be annoying to recalculate this stuff later on if you decide to change the speed of the transition to something other than 0.02, so lets nip this in the bud right now and start expressing that value this way:
startTransition = true
p = 0
speed = 0.02
steps = math.pi() / speed
camX = GetCameraX()
camY = GetCameraY()
startX = camX
startY = camY
destX = 0
destY = -3000
while gamerunning() do
if startTransition then
p = p + speed
if (p > math.pi()) then
p = math.pi()
startTransition = false
end
camX = startX + ((destX - startX) * p)
camY = startY + ((destY - startY) * p)
SetCameraPosition(camX, camY)
end
coroutine.yield()
end
end
During the transition we'll need to know how much to move by. We'll split it into vertical movement and horizontal movement.
First we'll need to know the total distance to move.
We get that with:
(destX - startX)
Then, we can divide that by the number of steps to get the average amount moved per step:
((destX - startX) / steps)
This gives us an amount which we can multiply together with math.sin (which is going to be a value starting at 0, increasing to 1, then going back down to 0).
So how will that work?
If the value was always 1, then we'd just have
steps number of cycles, each time the movement would be
((destX - startX) / steps) amount of movement.
Instead we have a value that starts on 0, increases to 1, then decreases again to 0.
So, hmm... how to solve that problem?
I'm not sure of it, but I would hazard a guess that if you multiply that math.sin by 2, you're going to end up with values ranging between 0 and 2, and that
the average amount of movement per step will be the same as if the value was a constant of 1.
In other words, I think if you multiply your sine by 2, you're going to end up with the correct amount of movement in total.
I might be wrong about that, but lets try and put together an implementation anyway. I'll leave you to troubleshoot it, if you wish.. :>
So we need to have:
(math.sin(p) * 2)
That should give us a value that ranges between 0 and 2 and 0 over the course of the transition.
Next we can put that together with the other stuff, to get this:
((destX - startX) / steps) * (math.sin(p) * 2)
That formula expresses how much we should move on each individual cycle, based on how far through the transition we are, what the start and destination coords are, and the number of steps (and thus the speed) in the transition.
So then we plug that into the code, and that gives us this:
startTransition = true
p = 0
speed = 0.02
steps = math.pi() / speed
camX = GetCameraX()
camY = GetCameraY()
startX = camX
startY = camY
destX = 0
destY = -3000
while gamerunning() do
if startTransition then
p = p + speed
if (p > math.pi()) then
p = math.pi()
startTransition = false
end
camX = startX + (((destX - startX) / steps) * (math.sin(p) * 2))
camY = startY + (((destY - startY) / steps) * (math.sin(p) * 2))
SetCameraPosition(camX, camY)
end
coroutine.yield()
end
end
Hope you've been able to follow this ok. Maybe you can see a little of my algorithm inventing process too...
I'd be interested to hear if it works. :>
Please post any corrections below guys, I'll edit when I have time. :>