+1 vote

I want to make a camera system which allow for larger area, while keeping all objects in view and also want to do camera zoom in and out depending on player proximity.

Here is reference link of what i want to achieve.

in Gossip

The main problem with this kind of camera is that it loops every object, this can be very slow; if there are many objects.

Godot 3.1 Alpha3 (Could also work on older versions) File: https://drive.google.com/open?id=1W4kh3_bCD6dl7h9Igwvk2JdJsJAWVQML

In Some ways the Godot version is easier, in other ways it is more difficult:
This script must be attached to a node, and will track the children of the node.
A Camera2D is needed.

``````extends Node2D
#Godot uses pixels, so this is a percentage 4 = 4%

func CalculateBox(InScreenSize):
#infinity for the min max formulas to work
var MinX = INF
var MaxX = -INF
var MinY = INF
var MaxY = -INF
#The way this works is it keeps the data from the nodes with the lowest -x,-y and highest x,y
for eachChild in self.get_children():
#Will only work with 2D, 3D needs transform.origin
var pos = eachChild.position

MinX = min(MinX,pos.x) # if pos.x is less than infinty keep it
MaxX = max(MaxX,pos.x) # if pos.x is more than negative infinty keep it

MinY = min(MinY,pos.y) # the next pass it compares the old kept value with the new
MaxY = max(MaxY,pos.y) # keeping the most relavent number for that corner

#Because Godot uses pixels we have to correct it
var CorrectPixel =(InScreenSize /100) * PaddingPercent

#Godot doesn't have a MinMaxRect but we can use a list
var FourPointList = [
MinX - CorrectPixel.y ,
MaxX + CorrectPixel.y ,
MinY - CorrectPixel.y ,
MaxY + CorrectPixel.y ]
#This will return a Rect2
return Rect2From4PointList(FourPointList)

#Special function for making a rect2 from the list
func Rect2From4PointList(InList):
#Formula AX+BX/2 AY+BY/2
var Center = Vector2( ((InList[0] + InList[1]) /2), ((InList[3] + InList[2]) /2) )
#Formula BX-AX BY-AY
var Size = Vector2( (InList[1] -InList[0]), (InList[3] - InList[2]) )
return Rect2(Center,Size)

func _process(delta):
#You must have a camera 2D for this to work
var ActiveCamera = get_node("../Camera2D") #Use the path to your camera
var ScreenSize = self.get_viewport().size

#This function will have to update every frame
var CustomRect2 = CalculateBox(ScreenSize)

var ZoomRatio = max(CustomRect2.size.x/ ScreenSize.x ,\
CustomRect2.size.y/ ScreenSize.y)

ActiveCamera.offset = CustomRect2.position
#ZoomRatio is a scalar so we need to turn it into a vector
ActiveCamera.zoom = Vector2(1,1) * ZoomRatio
``````
by (1,428 points)
selected by

I forgot. If you want to limit the zoom you only need to adjust the ZoomRatio at the end, like this:

``````ActiveCamera.zoom = Vector2(1,1) * max(ZoomRatio, 0.5)
``````

Now it will zoom in, to only half the normal size.
You can set a max like this:

``````ActiveCamera.zoom = Vector2(1,1) * min(ZoomRatio, 2)
``````

To Zoom out to only twice the normal size, or if you want both you can use clamp:

``````ActiveCamera.zoom = Vector2(1,1) * clamp(ZoomRatio, 0.5, 2.0)
``````

All of this code relies on min and max functions.

Thanks for the answer, can you tell me how we can adjust zoom in/out speed smoothly?

can you tell me how we can adjust zoom in/out speed smoothly?

In theory as long as all your objects move smoothly then the zoom should be smooth.
But if you want to double check:

At the top where you declare the variables for the script put this:

``````export var Smooth = 0.01
``````

This value tells the lerp how smooth it should be. Smaller is smoother. 0 will stop the zoom completely, while 1 is no smooth.

At the end you want this:

``````ActiveCamera.zoom = ActiveCamera.zoom.linear_interpolate( (Vector2(1,1) * ZoomRatio), Smooth)
``````

This line tells it to lerp between the last known zoom and the newest zoom. Using Smooth as the time factor.

if you then also want to clamp it you should do it something like this:

``````var ClampedZoom =  Vector2(1,1) * clamp(ZoomRatio, 0.5, 2.0)
ActiveCamera.zoom = ActiveCamera.zoom.linear_interpolate( ClampedZoom, Smooth)
``````

@MysteryGM, this is working great as expected but when camera zoom out all objects are on screen looks small, no doubt this is expected behaviour but i don't want to zoom out my player after certain level of camera zoom out so it can be visible to user and rest objects will zoom out as its happening now. How to achieve this? Can you plz help me on this? Thank you very much for your accurate answer.

Any words on this?