Techniques for Changing the Limits of Camera2D

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Diet Estus

I want to set the limits of a Camera2D attached to my player on a level-by-level basis, but I am not sure of the best method to do this.

What is a good method for setting rectangular camera limits on a level-by-level basis?

For example, limits which look like:

I was thinking that I could have some kind of rectangular node per level. When a level loads, I can access this node and set the limits of my camera using it (setting the camera’s limit_left, limit_top, etc. using the sides of the rectangle).

But what kind of node should I use? Area2D perhaps? Or maybe a ReferenceRect would be easier…

Eventually, I’d like my level geometry to dictate the limits of the camera on a sub-level basis. For example, if the player is in a narrow corridor, the camera wouldn’t scroll up or down. But in a large area, it would. I imagine I can achieve this by defining different rectangular shapes in my level and setting the camera limits when my player enters these shapes. But I am not sure of a good way to implement it.

What is a good method for setting complex camera limits?

For example, limits which look like:

:bust_in_silhouette: Reply From: kidscancode

It depends on how you’re laying out your level. For example, if you’re using a TileMap, you can use get_used_rect() to find its extents. This will limit your camera to the size of the map:

func set_camera_limits():
    var map_limits = $TileMap.get_used_rect()
    var map_cellsize = $TileMap.cell_size
    $Player/Camera2D.limit_left = map_limits.position.x * map_cellsize.x
    $Player/Camera2D.limit_right = map_limits.end.x * map_cellsize.x
    $Player/Camera2D.limit_top = map_limits.position.y * map_cellsize.y
    $Player/Camera2D.limit_bottom = map_limits.end.y * map_cellsize.y

If you’re building your level in some other way, you just need a way to find the rectangle that defines its extents. Odd shaped levels are going to make it more complicated, and yes, you’ll have to dynamically adjust them based on the area you’re in. Area’s area_entered() signal will be your friend for that.

Bonus points if you use a Tween to smoothly adjust camera limits when entering or exiting such an area :smiley:

markopolo | 2018-05-18 17:00

can anyone know about implementing limits for camera2D on isometric view?

muthu0914 | 2019-09-13 13:57

This works perfectly, but presents me with another challenge: I have certain visual elements as children of the camera (because I want them to follow it). Now when the camera stops at the tilemap limits, these elements nevertheless continue to move - which is unexpected, because I thought they’d stay bound to their parent node. Is there any quick fix for this? (I’ll try to solve it myself and if I do, I’ll report)

Moribunny | 2020-09-05 15:25

There’s a difference between the Camera’s position, which can continue to increase, and its limits.

The more correct way to do UI elements is to put them in a separate CanvasLayer rather than parenting them to the Camera node. Being on a separate layer, they will ignore the camera’ s transform and remain always “on screen”.

kidscancode | 2020-09-05 15:30

I’m trying to smoothly tween the limits but it isn’t smooth when I try to interpolate both limit_left and limit_right at the same time. Is there a solution for this?

dopey_kun | 2021-09-04 12:20

Hello, im a beginner and new to Godot Engine.
I tried your code and got this following error:
“Invalid get index ‘cell_size’ (on base: ‘TileMap’).”

Can you help me solve this problem? thanks

AgungGD | 2023-06-06 06:21

:bust_in_silhouette: Reply From: 2plus2makes5

In my opinion the easiest way is to use physics nodes.

You could make a custom camera class, something like this:
-kinematic character 2d/rigid body 2d/etc

and then in the level you put an area2d with collisionpolygons2d/collisionshapes2d delimiting the area in which the camera can move.

This way the camera shouldn’t surpass the limits.