Simple Camera2D drag script - There is a lag if you hold the mouse button, move and release in quick succession

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


so I’m trying to build a simple camera movement script that lets you drag the camera node with your mouse. The script below does work and you can move the camera very smoothly. However, if you hold down the mouse button and release it in quick succession (while moving the mouse), the camera does not move smoothly but rather jumps to the final position, as if a lot of “mouse movement” events aren’t sent out.

enter image description here

If you simply hold down the mouse button and then move very fast, it’s perfectly smooth, so there should be enough time for the system to call many “mouse movement” events.

Do you have an idea what’s happening here? Because this is slightly annoying and very noticeable if you just quickly click and drag, and I would love to fix that :smiley:


extends Camera2D

var mouse_starting_position
var starting_position
var is_dragging = false

func _ready():

func _input(event):
	if event is InputEventMouseButton:
		if event.is_pressed():
			starting_position = position
			mouse_starting_position = event.position
			is_dragging = true
			is_dragging = false
	if event is InputEventMouseMotion and is_dragging:
		position = starting_position - zoom * (event.position - mouse_starting_position)

Has anyone acknowledged this issue or know what can be done to stop it?

In my case, I am moving objects around smoothly on the screen (like a 2D scroller). However, a mouse click causes a noticeable ‘pause’ in rendering the camera even though it is moving because the next refresh it has moved several tiles.

BurningSpear | 2022-10-19 17:21

:bust_in_silhouette: Reply From: Midonk

Hey there ! Well your code makes effectively a delta between the mouse_starting_position and the actual mouse position so the behaviour here is normal.

If you want to smooth this movement… I think you could use a Tween but the implementation might be…tricky


You can try to linearly interpolate the positions in a certain time interval but this may result (in both case) in a offsetted follow of your mouse.

It’s up to you to test what you wanna do but if you want to keep a reactive camera…the actual behaviour is the best one or with a really short interpolation

:bust_in_silhouette: Reply From: decepticlown

That is happening because you don’t have effective way to distinguish between a click and drag. User needs a certain time threshold to margin out the errors between fast click and sustained drag. Try this:

extends Camera2D

export var drag: float = 0.2

var clicked
var current_pos
var last_pos
var new_position = null
var stored_position = position

var click_timer =
const click_threshold = 0.2

func _ready():
    click_timer.one_shot = true

    last_pos = get_viewport().get_mouse_position()

func _process(delta):
    current_pos = get_viewport().get_mouse_position()
    if clicked:
	    new_position = position - (current_pos - last_pos) * zoom
    elif new_position: position = position + (new_position - position) * drag
    last_pos = current_pos

func _input(event):
    if event is InputEventMouseButton:
	    clicked = event.pressed
	    if clicked:
		    if click_timer.is_stopped():
		    if !click_timer.is_stopped():
    elif event is InputEventMouseMotion:
	    if clicked:
		    stored_position -= event.relative * zoom
		    if click_timer.is_stopped():
			    position = stored_position
		    stored_position = position

If you don’t like the jump in the drag animation just put this line inside the if condition:

stored_position -= event.relative * zoom
if click_timer.is_stopped():
    position = stored_position

Like this:

if click_timer.is_stopped():
    stored_position -= event.relative * zoom
    position = stored_position

decepticlown | 2021-12-29 11:42