+2 votes

Hi -

Trying to drag and drop a sprite, I was able to get this to work. Basically, I detect the size and position of sprite and compare it to mouse_position. But I can't help but think there is a better way. For one, I know I could remove some of those checks into variables to make it more readable. Also, the sprite snaps its center onto mouse pointer. I could clean this all up, but want to make sure I'm heading in the right direction or if there is an out of the box approach. (I know there is for Controls, but I don't think those methods are accessible to Nodes). Any help is appreciated. Thanks !

var can_grab = false
var grabbed = false
#Location of where we grabbed the sprite
var grabbed_start = Vector2()

func _input(event):
    if event.is_action_pressed("click_left") and !grabbed:
        #detects that pointer is within dimension of Sprite
        if get_global_mouse_position().x > $Sprite.position.x - ($Sprite.texture.get_size().x/2) && get_global_mouse_position().x < $Sprite.position.x - ($Sprite.texture.get_size().x/2) + $Sprite.texture.get_size().x:
            if get_global_mouse_position().y > $Sprite.position.y - ($Sprite.texture.get_size().y/2) && get_global_mouse_position().y < $Sprite.position.y - ($Sprite.texture.get_size().x/2) + $Sprite.texture.get_size().y:
                grabbed = true
                grabbed_start = get_global_mouse_position()
    if event.is_action_released("click_left") and grabbed:
        grabbed = false
        var grabbed_end = get_global_mouse_position()
        $Sprite.position = event.position
        var sprite_pos = $Sprite.position
    elif event is InputEventMouseMotion:
        if grabbed:
            $Sprite.position = event.position
in Engine by (42 points)
edited by

1 Answer

+8 votes
Best answer

Okay. Found part of the answer. Looks like this was actually asked quite a bit.

The best way to do this is ensure the KinematicBody2D has its pickable flag set in the inspector. Then it can treating more like a GUI control and there's no need work with the sprite's texture.

Here's a link: https://godotengine.org/qa/34536/simple-click-2d-how-to-tell-when-static-body-has-been-clicked

For the mouse pointer snapping issue (if this is not a desired effect for you), just find the difference of the offset and add it back in when the object is clicked. Still a little delay on the drag, but I think this could be taken care of with a tween behavior to make it feel a little more intentional, but that's just my opinion. good luck.

extends KinematicBody2D

# Pickable needs to be selected from the inspector

var can_grab = false
var grabbed_offset = Vector2()

func _input_event(viewport, event, shape_idx):
    if event is InputEventMouseButton:
        can_grab = event.pressed
        grabbed_offset = position - get_global_mouse_position()

func _process(delta):
    if Input.is_mouse_button_pressed(BUTTON_LEFT) and can_grab:
        position = get_global_mouse_position() + grabbed_offset
by (42 points)

1 year later in this comment still comes in clutch. That part about the offset saved me on such a headache, ty!

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 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 webmaster@godotengine.org with your username.