stop dragging when KinematicBody2D collides

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

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 mouse_entered and mouse_existed 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,

:bust_in_silhouette: Reply From: GameVisitor
_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 :slight_smile:

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.

wakry | 2019-03-10 11:36

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. move_and_collide() just stops the body’s movement when a collision occurs. *

GameVisitor | 2019-03-10 18:48

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?

wakry | 2019-03-10 19:40

:bust_in_silhouette: Reply From: wakry

Thanks to @Fabián on Godot Discord. My problem was in setting the position directly and not using move_and_collide . 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)