Camera goes beyond limits

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

I have an overhead top down camera setup for my game and i use the mouse to scroll it, but when the camera reaches its set limits (left : -1000, Top : -500, right: 3000, bottom : 2500) it goes beyond it but the viewport doesn’t, how do i clamp the camera to only move within the set limits and not beyond, thanks in advance! (camera code below)

    extends Camera2D

var is_panning = true;
var cam_spd = 10

onready var editor = get_node("/root/World/Cam_container")
onready var editor_cam = editor.get_node("Camera2D")
onready var maptype = get_node("/root/World/Compositemaps").maptype

func _positioner():
	if maptype == 'dungeonmap1':
			 position = Vector2(152,64)
	elif maptype == 'dungeonmap2':
			 position = Vector2(1592,1360)
	elif maptype == 'dungeonmap3':
			 position = Vector2(1680,144)
	elif maptype == 'dungeonmap4':
			position = Vector2(1432,1576)

func _ready():
	_positioner()
	editor_cam.current = true
func _process(_delta):
	
	move_editor()
	is_panning = Input.is_action_pressed("mb_left")
	pass
	
func move_editor():
	if Input.is_action_pressed("w"):
		editor.global_position.y -= cam_spd
	if Input.is_action_pressed("a"):
		editor.global_position.x -= cam_spd
	if Input.is_action_pressed("s"):
		editor.global_position.y += cam_spd
	if Input.is_action_pressed("d"):
		editor.global_position.x += cam_spd
	pass
	
func _unhandled_input(event):
	if(event is InputEventMouseButton):
		if(event.is_pressed()):
			if(event.button_index == BUTTON_WHEEL_UP):
				editor_cam.zoom += Vector2(0.1,0.1)
			if(event.button_index == BUTTON_WHEEL_DOWN):
				editor_cam.zoom += Vector2(0.1,0.1)
	if(event is InputEventMouseMotion):
		if(is_panning):
			editor.global_position -= event.relative * editor_cam.zoom
	pass

video of what happens : 2022-11-14 06-36-08

:bust_in_silhouette: Reply From: DDoop

I’m a little confused trying to guess what the scene hierarchy you are working with looks like. Is the object attached to the script you have provided the main camera?

To me it looks like you need to clamp the individual components of the global_position inside move_editor() after the global_position vector is modified. I would replace pass with:

editor.global_position.x = clamp(editor.global_position.x, -1000, 3000)
editor.global_position.y = clamp(editor.global_position.y, -500, 2500)

My apologies if I am misunderstanding what exact object you are trying to fix inside the given area but clamp()'ing the vector components is how (provided you can then assign back into the same variable which you should be able to here). The clamp() call needs to be done after whatever movement the object performs that potentially could take it out of the desired area (one could also cause clamp() to fire conditionally if performance became an issue later but don’t try setting that up unless it becomes necessary).

That worked, thank you so much!

Viltra | 2022-11-14 23:36

is there a way to clamp the zoom too ?

Viltra | 2022-11-14 23:39

nvm made it work too, thanks!

Viltra | 2022-11-14 23:44

Clamp will always return either the provided value, the minimum, or the maximum. Inside _unhandled_input() after both conditional blocks that modify the zoom property, just add something like:

zoom = clamp(zoom, min, max)

You’ll need to specify the min and max, though.

A note on your code overall: Is there a reason that you refer to zoom and global_position via a local instance variable? If you remove all the editor_cam references, does it still behave the way you want? Since your script extends Camera I have a feeling you are going through too much work to get a reference to self, but I can imagine reasons to make it like that.

DDoop | 2022-11-14 23:46