Spring It's New Camera Movement

It has been a busy past two weeks so I missed posting last week.  Last Friday I started working on filling out the areas around our spring it levels.  When I started doing this, I realized that once the camera was able to zoom, the area that I need to cover would have to be changed as well.

Camera Movement.jpg

In the diagram above, the Full size of the level is represented by the black box on the left of the picture.  The Green tetrahedron-like object represents the camera's view screen when fully zoomed out.  So, to make sure the camera cannot move in the X or Y directions, I would just have simple if statements check those bounds.  The problem would then arise when the camera would zoom in.  The green camera view port would move along the red line labeled 1 until it was the size of the blue camera view port.  If the same limits that applied to the blue camera also applied to the green camera, the player would not be able to see anything with the blue camera.  It was clear I needed to make the camera movement limits dependent upon how far zoomed in or out the player was.


  After taking a look at the varying level sizes, I decided that the camera's maximum zoom distance will depend on the level.  Meaning the camera will have to stop once it can see the entire height or width do the scene, whatever comes first.  So, I started by writing a function in the level loader to determine the max zoom distance. So after some basic algebra to determine the equations of the lines and their intersection points, I ended up with the following code.

//The Camera Zooming Out needs to be limited to only showing the entire level length or height in one view (Thsi will determien which one will be shown first and will set the limit at that)
float SetCameraZoomOutMax(){

//The limits of the camera's movement equation was determined in two parts. The first part is from (5.5, y, -10) to (9.5, y, -20).
//After -20 its movtion follows a different equation based off (9.5, y, -20) and (24, y, -37).
//Where this line form each side of the level meets means there is the x limit
float zoomOutLimitForWidth = (-17f/29f) * ((int)mLevelWidth * (int)mLevelScaling + 15.12f);

//Both the top and bottom have different equations and where those two equations intersect will determine where your backward limit is
//These equations are the equations that dictate movement
float zoomOutLimitForHeight = (-7f/13f * (((int)mLevelHeight * (int)mLevelScaling) + 30.14f));

if(zoomOutLimitForWidth > zoomOutLimitForHeight){
return zoomOutLimitForWidth;
}
else{
return zoomOutLimitForHeight;
}

}

Using the same equations I developed to determine the Max Distance the camera can zoom out, I was able to set limits on the camera's movement depending on how far the player was zoomed in. the problem I found was that two equations were needed:  One equation would get the player from their minimum zoom in distance to the camera's start position at z = -20, the second equation would dictate movement from the start position to their furthest point.  The reason was that once the camera was further out, the slope of the limits steepened.  This process most likely could have been done with one non linear equation, but this method is easier on me and accomplishes what I wanted.

In the code below:

LW = Level Width

LH = Level Height

float CalculateVariableCameraMoveZoneLimits(string incomingDirection) {

//This is the x or y limit depending on what case is encountered
float currentLimit = mMouseMoveZone;
float zPosition = this.transform.position.z;

switch(incomingDirection){


default: break;


case "right":
if(zPosition > -20){
//Xright close: LW + 4/10 * z - 1.5 = y
currentLimit = mLevelSize.x + 4f/10f * zPosition - 1.5f;
}
else{
//Xright far: LW + 14.5/17 * z + 7.5 = y
currentLimit = mLevelSize.x + 14.5f/17f * zPosition + 7.5f;
}
break;

case "left":
if(zPosition > -20){
//Xleft close equation -4/10 * z + 1.5 = y
currentLimit = -4f/10f * zPosition + 1.5f;
}
else{
//Xleft far: -14.5/17 * z - 7.5
currentLimit = -14.5f/17f * zPosition - 7.5f;
}
break;

case "down":
if(zPosition > -20){
//Ylower close: -7/10*z = y
currentLimit = -7f/10f * zPosition;
}
else{
//Ylower far: -6/7*z - 3.14 = y
currentLimit = -6f/7f * zPosition -3.14f;
}
break;
case "up":
if(zPosition > -20){
//Yupper: -LH/10 * z + 7 - LH = y
currentLimit = (-mLevelSize.y * 10f / zPosition) + 7;
}
else{
//Yupper: z + LH + 27 = y
currentLimit = zPosition + mLevelSize.y + 27;
}
break;

}

return currentLimit;
}

The Camera system will still need more upgrades as the game progresses.  Notably, changing camera movement speed based on scroll distance.  This would cause the player to move slower when zoomed in and faster when zoomed out.  This would be relatively simple for me to implement, but because of upcoming GDC, it is not on our current sprint.

The second system I hope to implement is change how zooming out works when the player crosses a movement limit.  Currently the player can zoom in, move all the way to the left or right of the screen, then zoom out.  When they zoom out, they will go directly backwards, moving out of the limits I set for horizontal and vertical movement.  This then allows the player to see the ugly Unity blue around all levels. To fix this I plan to  put similar checks into the zooming out motion, but instead of preventing movement, the camera will just be moved horizontally or vertically and before zooming out.  Hopefully creating a smooth zooming motion for the player.