Moving a camera without a player?

Godot Version



Hi, I’m new and experimenting and trying to make a hex style board game.
Right now I just wanna do the basics. I want to implement a camera my first jank thought was an invisible player that the camera follows but I don’t wanna do that.
What’s the best method to implement a camera that can be tied to WASD, Arrow keys, MMB drag and right click drag ? Do I still use camera2d or is there another type of camera to use in this ?

1 Like

Move the camera node directly by attaching a script and handle user input.

I already have a script attached with input being listened to and is printing so I know the inputs work.

extends Camera2D

func _input(event): 
	# print(event)
	if event.is_action_pressed("MoveCamUp"):		
	if event.is_action_pressed("MoveCamDown"):
	if event.is_action_pressed("MoveCamLeft"):
	if event.is_action_pressed("MoveCamRight"):
	#if event.is_action_pressed("CamMMBPan"):
	#	print("CamMMBPan")

but how do I manipulate the camera where do I go from here ? Like what do I use input to make the camera move ?

Camera2d inherites from node2d so it has a position and transform you can manipulate. Anything a node2d can do so can a camera2d.

#Move right
position.x += speed

You can shorten this code by using

Func _input(_event):
  var direction: Vector2 = Input.get_vector(left action, right action, up_action, down_action). 

  position += direction * speed

It may be advantageous to do that in a process or physics processes function to pull the input at a constant rate.


Okay I have tried the first method as the long version which I don’t mind.

extends Camera2D

var ZoomMin = Vector2(0.25,0.25)
var ZoomMax = Vector2(2.5,2.5)
var ZoomSpd = Vector2(0.3,0.3)
var PanSpeedKey = 8
# Called when the node enters the scene tree for the first time.
func _ready():
	pass # Replace with function body.

func _input(event):
	if event.is_action_pressed("ScrollZoomOut"):
		if zoom > ZoomMin:
			zoom -= ZoomSpd
		print("Zoom out")
	if event.is_action_pressed("ScrollZoomIn"):
		if zoom < ZoomMax:
			zoom +=ZoomSpd
		print("Zoom in")

# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(_delta):
	if Input.is_action_pressed("MoveCamUp"):
		position.y -= PanSpeedKey
	if Input.is_action_pressed("MoveCamDown"):
		position.y += PanSpeedKey
	if Input.is_action_pressed("MoveCamLeft"):
		position.x -= PanSpeedKey
	if Input.is_action_pressed("MoveCamRight"):
		position.x += PanSpeedKey

How is this ? Zoom is kinda janky and thrown together with what I’ve learned off youtube. I guess my current task is setting the speed at certain zoom levels ?

1 Like

Thatha good yes!

I guess you could adjust speed yes I would suggest using the global easing function to scale your speed over your distance level… To really smooth movement you can try linear interpolation.

For a single float value there is a global function called lerpf that takes three float input: current, target, and lerp percentage.

zoom = lepf(zoom, input_zoom, 0.3)

Where your input handling will update the input_zoom value and this line here will be on a process function updating the camera “zoom”.

Or you can pull the input in the process function two and do the zoom of you like. The percentage factor can be adjusted depending on how fast you want it to adjust. You can also dynamic adjust it depending on user preferences.

If you want a non-linear movement look at the easing function it will help you customize any sort of interpolation you want. Unless you want a bezier curves… but it can still do a lot and you can export a variable to the node editor and get a graphical editor of the curve.

This can also be applied to your movement as well!

The world is yours now!


There is also a clamp function that you can simplify your logic.

If I put zoom in:
  Zoom_input+= zoomstep
If input zoom out:
 Zoom_input -= zoomstep

I’m a little confused with what would be Zoom_input? Would that be the input function turned into a var or ?
Also I have an issue where if I set a limit to the camera the position of the camera ignores the limit and keeps going leaving the view port behind.

sorry, been typing on my phone by memory.

the clamp function will return a value. Ill make it more confusing by just abandoning my previous two namings.

myvalue = clamp(myvalue,min,max)

the clamp value can take vectors as well, but it will clamp all values to the min, or max, even if only one axis is out of bounds.

but yea. at least for camera zoom in 2d you can modify the Vector2 zoom value by taking whatever the zoom value is multiplied by a scaler.

# untested and some pseudo code
self.zoom # is a Vector2
var zoom_scalar : float = 1.0
const ZOOM_STEP: float = 0.1
var target_zoom : Vector2 = Vector2.ONES

func _input(event):
  if event is zoom_out:
    zoom_scalar += ZOOM_STEP
  if event is zoom_in:
    zoom_scalar -= ZOOM_STEP
  zoom_scalar = clamp(zoom_scalar, min, max)
  target_zoom  = Vector2.ONES * zoom_scalar

func _process(delta):
  zoom = zoom.lerp( target_zoom,  0.5)
1 Like

if you need to find stuff fast use the doc help button under the scripting tab

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.