0 votes

Hi,

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 :D

Thanks!

extends Camera2D

var mouse_starting_position
var starting_position
var is_dragging = false

func _ready():
    pass

func _input(event):
    if event is InputEventMouseButton:
        if event.is_pressed():
            starting_position = position
            mouse_starting_position = event.position
            is_dragging = true
        else: 
            is_dragging = false
    if event is InputEventMouseMotion and is_dragging:
        position = starting_position - zoom * (event.position - mouse_starting_position)
Godot version 3.4.2
in Engine by (12 points)

2 Answers

0 votes

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

OR

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

by (167 points)
0 votes

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 = Timer.new()
const click_threshold = 0.2

func _ready():
    click_timer.one_shot = true
    add_child(click_timer)

    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():
                click_timer.start(click_threshold)
        else:
            if !click_timer.is_stopped():
                click_timer.stop()
    elif event is InputEventMouseMotion:
        if clicked:
            stored_position -= event.relative * zoom
            if click_timer.is_stopped():
                position = stored_position
        else:
            stored_position = position
by (123 points)
edited by

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
Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read Frequently asked questions and How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to [email protected] with your username.