### Author Topic: CLEAN camera transitions x,y to x,y  (Read 1263 times)

0 Members and 1 Guest are viewing this topic.

#### Tomfloria

• Shrub
• Thank You
• -Given: 0
• Posts: 232
• First iOS modder :D
##### CLEAN camera transitions x,y to x,y
« on: May 08, 2012, 06:11:43 PM »
Right, i've had a little chat with Alex and he's helped me quite a bit, he gave me this code which I changed a bit because it wasn't a function.

This is at the start of levellogic

Code: [Select]
`      startTransition = true    p = 0    camX = GetCameraX()    camY = GetCameraY()    startX = camX    startY = camY    destX = 0    destY = -3000`
Code: [Select]
`    while gamerunning() do  if startTransition then    p = p + 0.02    if (p > 1) then      p = 1      startTransition = false    end    camX = startX + (destX - startX) * p    camY = startY + (destY - startY) * p    SetCameraPosition(camX, camY)       end       coroutine.yield()    endend`
and then things get crazy... Whatdup. XD

#### Tomfloria

• Shrub
• Thank You
• -Given: 0
• Posts: 232
• First iOS modder :D
##### Re: CLEAN camera transitions x,y to x,y
« Reply #1 on: May 08, 2012, 06:12:27 PM »
I forgot to mention that the effect im going for is clean transitions from x,y to x,y, not just jumping from x,y to x,y

#### annikk.exe

• Achiever
• Ent
• Thank You
• -Given: 0
• Posts: 1,794
##### Re: CLEAN camera transitions x,y to x,y
« Reply #2 on: May 14, 2012, 03:49:56 PM »
Hmm.  I see what you are trying to do, and the code looks ok...

Lets work it out for some possible values.

Code: [Select]
`    startTransition = true    p = 0    camX = GetCameraX()    camY = GetCameraY()    startX = camX    startY = camY    destX = 0    destY = -3000`
Lets use the following test values:

camX = 2000
camY = -3000
startX = 2000
startY = -3000
destX = 500
destY = 500

Then lets plug those into the code.

First we run this portion:
Code: [Select]
`    while gamerunning() do  if startTransition then    p = p + 0.02    if (p > 1) then      p = 1      startTransition = false   end`
startTransition is true, so on the first run through of this code, p (currently 0) will become 0.02.
P is not more than 1, so the If conditional is not triggered, and startTransition remains true.

p = 0.02
startTransition = true

Next we come to this part:
Code: [Select]
`    camX = startX + (destX - startX) * p    camY = startY + (destY - startY) * p    SetCameraPosition(camX, camY)       end`
Lets focus only on the camX variable.
Remeber, startX = 2000 and destX = 500.

camX = startX + (destX - startX) * p
becomes
camX = 2000 + (500 - 2000) * 0.02
camX = 2000 - 1500 * 0.02

Here there's a possible point where we could run into trouble...  it's not clear whether the sum should be (2000 - 1500) * 0.02 = 10, or if it should be 2000 - (1500 * 0.02) = 1970.

10 and 1970 are dramatically different results.  We want the X transition to start from 2000 and proceed toward 500.  So 1970 sounds more like it than 10!

I think the crazyness you are seeing is a result of Lua naturally choosing the wrong mathemathetical route, as per above, and ending up with stupid values like 10.

I think the calculation you should be doing is:

Code: [Select]
`    camX = startX + ((destX - startX) * p)    camY = startY + ((destY - startY) * p)`
If you change those two lines to be like I have them there, I bet you it works. :>
« Last Edit: May 14, 2012, 06:41:42 PM by annikk.exe »

#### annikk.exe

• Achiever
• Ent
• Thank You
• -Given: 0
• Posts: 1,794
##### Re: CLEAN camera transitions x,y to x,y
« Reply #3 on: May 14, 2012, 06:05:57 PM »
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:

Code: [Select]
`    if (p > 1) then      p = 1      startTransition = false    end`
and to this code:

Code: [Select]
`    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:

Code: [Select]
`      startTransition = true    p = 0    speed = 0.02    steps = math.pi() / speed    camX = GetCameraX()    camY = GetCameraY()    startX = camX    startY = camY    destX = 0    destY = -3000`
Code: [Select]
`    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()    endend`

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:

Code: [Select]
`(destX - startX)`
Then, we can divide that by the number of steps to get the average amount moved per step:

Code: [Select]
`((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:

Code: [Select]
`(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:

Code: [Select]
`((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:

Code: [Select]
`    startTransition = true    p = 0    speed = 0.02    steps = math.pi() / speed    camX = GetCameraX()    camY = GetCameraY()    startX = camX    startY = camY    destX = 0    destY = -3000`

Code: [Select]
`    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()    endend`

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. :>
« Last Edit: May 15, 2012, 10:26:07 AM by annikk.exe »

#### Aino

• Ent
• Thank You
• -Given: 1
• Posts: 1,483
• They'll eat you next!
• Eufloria: Yes
##### Re: CLEAN camera transitions x,y to x,y
« Reply #4 on: May 14, 2012, 08:23:16 PM »
Seems that you're talking about the Sine, not Cosine

Also, something I came up with just looking at your codes:

(It's just to show of an idea, it might not work!)
Code: [Select]
`camX = startX + (destX - startX) * math.sin(GetCameraX()/destX*math.pi)camY = startY + (destY - startY) * math.sin(GetCameraY()/destY*math.pi)`
this should work immeadiatly when you allocate a new destination for X or Y, and it's give a smooth transition that Annikk was talking about. Though I don't know if the code works for the iOS version...

#### annikk.exe

• Achiever
• Ent
• Thank You
• -Given: 0
• Posts: 1,794
##### Re: CLEAN camera transitions x,y to x,y
« Reply #5 on: May 14, 2012, 08:26:08 PM »
Seems that you're talking about the Sine, not Cosine

You're right :>  I got the lines mixed up in the legend.
I'll edit. :>

#### annikk.exe

• Achiever
• Ent
• Thank You
• -Given: 0
• Posts: 1,794
##### Re: CLEAN camera transitions x,y to x,y
« Reply #6 on: May 15, 2012, 10:24:29 AM »
Also, something I came up with just looking at your codes:

(It's just to show of an idea, it might not work!)
Code: [Select]
`camX = startX + (destX - startX) * math.sin(GetCameraX()/destX*math.pi)camY = startY + (destY - startY) * math.sin(GetCameraY()/destY*math.pi)`

Don't think that would work because it doesn't take the number of steps into account..  we need to know the average step length so that we can multiply it with the math.sin to get the smoothing.

I'm not sure mine will work either though.  Looking forward to hearing.. :>  I've done quite a bit of editing now so it's reasonably well explained, I think...

#### Aino

• Ent
• Thank You
• -Given: 1
• Posts: 1,483
• They'll eat you next!
• Eufloria: Yes
##### Re: CLEAN camera transitions x,y to x,y
« Reply #7 on: May 15, 2012, 01:57:14 PM »

Don't think that would work because it doesn't take the number of steps into account..  we need to know the average step length so that we can multiply it with the math.sin to get the smoothing.

I'm not sure mine will work either though.  Looking forward to hearing.. :>  I've done quite a bit of editing now so it's reasonably well explained, I think...

I guess this one will:

Code: [Select]
`time = 30camX = startX + (destX - startX) * math.sin(GetCameraX()/destX*math.pi) / timecamY = startY + (destY - startY) * math.sin(GetCameraY()/destY*math.pi) / time`
I should automatically adjust and us as long time as it needs

I'll test it out actually, just for fun

#### annikk.exe

• Achiever
• Ent
• Thank You
• -Given: 0
• Posts: 1,794
##### Re: CLEAN camera transitions x,y to x,y
« Reply #8 on: May 15, 2012, 02:51:18 PM »
You haven't defined Time...

#### annikk.exe

• Achiever
• Ent
• Thank You
• -Given: 0
• Posts: 1,794
##### Re: CLEAN camera transitions x,y to x,y
« Reply #9 on: May 15, 2012, 02:52:54 PM »
See, here is where our strategies diverge, Aino.  I sit and think about the problem for ages, and use lots of diagrams and exercises and work out small bits of the puzzle, before finally using the conceptual understanding I've gained to piece all the parts of the puzzle together.... whereas you just come straight out with an attempt at a formula. :>

#### Aino

• Ent
• Thank You
• -Given: 1
• Posts: 1,483
• They'll eat you next!
• Eufloria: Yes
##### Re: CLEAN camera transitions x,y to x,y
« Reply #10 on: May 15, 2012, 03:17:22 PM »
Well Annikk: my subconsciousness do a lot of math apparently, because suddenly I have a formula in my head which I don't know the origin of except some inspiration from other sources

Edit: And FYI: the formula works, but fails at some points... Going back to trigonometry! haha

#### Tomfloria

• Shrub
• Thank You
• -Given: 0
• Posts: 232
• First iOS modder :D
##### Re: CLEAN camera transitions x,y to x,y
« Reply #11 on: May 15, 2012, 04:00:22 PM »
Get you're codes right boys and who's code is right, and what am I adding haha

#### Tomfloria

• Shrub
• Thank You
• -Given: 0
• Posts: 232
• First iOS modder :D
##### Re: CLEAN camera transitions x,y to x,y
« Reply #12 on: May 15, 2012, 06:21:52 PM »
Right nerds :p going to try it!

#### Aino

• Ent
• Thank You
• -Given: 1
• Posts: 1,483
• They'll eat you next!
• Eufloria: Yes
##### Re: CLEAN camera transitions x,y to x,y
« Reply #13 on: May 15, 2012, 06:30:35 PM »
Here you go

#### Tomfloria

• Shrub
• Thank You
• -Given: 0
`function LevelLogic() StartLevelLogic() --CameraTest() --MAKE SURE THERE IS -- BEFORE ACTUAL RELEASE YOU IDIOT...     startTransition = true    p = 0    camX = GetCameraX()    camY = GetCameraY()    startX = camX    startY = camY    destX = 0    destY = -3000 foundAsteroid1 = false foundAsteroid2 = false --In the game there are messages and what not, but i've deleted them for this purposeWaitReal(4)    destX = 10000    destY = 10000WaitReal(4)    destX = 20000    destY = 20000 while GameRunning() do if startTransition then p = p + 0.02 if (p > 1) then p = 1 startTransition = false end camX = startX + ((destX - startX) * p) camY = startY + ((destY - startY) * p) end CheckConditions() coroutine.yield() endend`