+1 vote

I wrote the following code for drag and drop:

func _input(event):
if event is InputEventMouseButton:
    if event.is_pressed() && mouse_entered:
        draggingDistance = position.distance_to(get_viewport().get_mouse_position())
        dir = (get_viewport().get_mouse_position() - position).normalized()
        dragging = true
    else:
        dragging = false
elif event is InputEventMouseMotion:
    if dragging:
        position = get_viewport().get_mouse_position() - draggingDistance * dir
pass

where mouseentered and mouseexisted are mouse events.

I am having trouble stopping the object from moving with the mouse if it collides

What I tried so far:

func _process(delta):
var collided = move_and_collide(Vector2(0, 0))
if collided != null:
    dragging = false
pass

It doesn't work as I really want it to be. It's glitchy and if I moved the mouse fast it just gets to the other side of the object it collided with.

1: desired movement
works only with slow mouse movement

2: when I move the mouse fast:
enter image description here

any idea how I can do this in a clean way?

Thank you,

asked Mar 10, 2019 in Engine by wakry (28 points)
edited Mar 10, 2019 by wakry

2 Answers

+1 vote
Best answer

Thanks to @Fabián on Godot Discord. My problem was in setting the position directly and not using moveandcollide . With fast mouse movement you don't get all the mouse positions that it went over, so some position might be missing.

To fix this I modified my code to be

func _input(event):
if event is InputEventMouseButton:
    if event.is_pressed() && mouse_entered:
        draggingDistance = position.distance_to(get_viewport().get_mouse_position())
        dir = (get_viewport().get_mouse_position() - position).normalized()
        dragging = true
    else:
        dragging = false
elif event is InputEventMouseMotion:
    if dragging:
        var newPosition = get_viewport().get_mouse_position() - draggingDistance * dir
        move_and_collide(newPosition - position )
pass

I also removed the code in the _process(delta)

answered Mar 10, 2019 by wakry (28 points)
0 votes
_input
_process

and

_physics_process

are all callback functions that the engine trigger so you write your own custom code.
You can stop executing your logic by setting them to false, ex : set_physics_process( false ) instead of dragging = false.

You could also disable collision, ex : $CollisionShape.disabled = true

Hope this helps :-)

answered Mar 10, 2019 by GameVisitor (834 points)

I am not looking into disabling the physics or the collision. I just want to stop the momvent when it collided. Just like if the user picks up something and if it hits something else it drops and the user has to pick it up again and move it to another way. Please check the gifs I added to the question that explains the problem.

Ok, I am no expert in 2D collisions, but now that your problem is clearer, can you use move_and_collide() ? as indicated here:

*Anything you do with move_and_slide() can also be done with move_and_collide(), it just might take a little more code.Run the scene again and try moving into the obstacle. You’ll see that the KinematicBody2D can’t penetrate the obstacle. However, try moving into the obstacle at an angle and you’ll find that the obstacle acts like glue - it feels like the body gets stuck.

This happens because there is no collision response. moveandcollide() just stops the body’s movement when a collision occurs. *

Is there a reason the collision response is not happening when I move the mouse fast, but it does happen when I move it slowly?

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.