0 votes

I want to be able to touch a physics body and drag it around the screen.

How do I do it?

Please Help .... I m new to this engine.

in Engine by (12 points)

3 Answers

–4 votes

You want to move the body around in the scene editor, or while running the game?

by (58 points)

I want to move the body around while running the game.....like this :

**https://www.youtube.com/watch?v=1kcbjcAdEQM**

+4 votes

The way I've done it is using a RigidBody2D, I have a script on the RigidBody2D.

In the Inspector tab for the RigidBody2D set CollisionObject2D -> Input -> Pickable as true.
Then make a connection for the signal input_event on the RigidBody2D
If you made the connection through the Scene tab in the editor it should make a function in the script with something like this:

func _on_RigidBody2D_input_event( viewport, event, shape_idx ):
    pass

With this you'll be able to get input events only when they are clicked on the RigidBody2D.
What I do is have a var that checks if the object is being held or not.

var is_held = false
func _on_RigidBody2D_input_event( viewport, event, shape_idx ):
    if event.type == InputEvent.MOUSE_BUTTON and event.pressed and event.button_index == BUTTON_LEFT:
        is_held = true

And to release the RigidBody2D we will need to use the normal input event.

var is_held = false
func _ready():
    set_process_input(true)

func _input(event):
    if event.type == InputEvent.MOUSE_BUTTON and not event.pressed and event.button_index == BUTTON_LEFT:
        is_held = false

func _on_RigidBody2D_input_event( viewport, event, shape_idx ):
    if event.type == InputEvent.MOUSE_BUTTON and event.pressed and event.button_index == BUTTON_LEFT:
        is_held = true

Now to make the object actually move. Since it's a RigidBody2D we can use the _integrate_forces() function.

var is_held = false
func _ready():
    set_process_input(true)

func _integrate_forces(state):
    var lv = state.get_linear_velocity()
    
    if is_held:
        lv = (get_viewport().get_mouse_pos() - get_pos()) * 16
    
    state.set_linear_velocity(lv)

func _input(event):
    if event.type == InputEvent.MOUSE_BUTTON and not event.pressed and event.button_index == BUTTON_LEFT:
        is_held = false

func _on_RigidBody2D_input_event( viewport, event, shape_idx ):
    if event.type == InputEvent.MOUSE_BUTTON and event.pressed and event.button_index == BUTTON_LEFT:
        is_held = true

And that should do it. The Object will be picked up when you click and hold on to it. And it will follow your mouse around until you let go.

You can see an example usage of this in a game I made for a jam, here: Pet Rock

by (678 points)
edited by

I tried to do exactly the same thing but I can not access to

func_on_RigidBody2D_input_event( viewport, event, shape_idx ):  

any help ?

doesnt make any sense to me,
event.pressed ?
event.button_index
.
it is not inside ImputEvent
http://docs.godotengine.org/en/stable/classes/class_inputevent.html#class-inputevent-is-action-pressed
.
is this another version of gdscript ? what i did wrong ?

Hey Marcus,
I have posted an updated answer here for Godot 3.
Check it out if you still have any problems!

+2 votes

UPDATED: This should work in 3.1.1

Since CowThing's answer seems to be from the days of old Godot 2 and no longer compatible with Godot 3, I have rewritten it:

  1. Create a RigidBody2D
  2. In the Inspector tab: Enable CollisionObject2D > Pickable
  3. Add this to your script:

    extends RigidBody2D
    
    export var mouse_drag_scale = 20
    var _is_picked = false
    
    func _input_event(viewport, event, shape_idx):
        if _event_is_left_click(event): # check if left click is pressed on the body
            _is_picked = event.pressed
    
    func _input(event): # check if left click is released even outside of the body
        if _event_is_left_click(event) and not event.pressed:
            _is_picked = false
    
    func _event_is_left_click(event):
        return event is InputEventMouseButton and event.button_index == BUTTON_LEFT
    
    func _integrate_forces(state):
        if _is_picked:
            state.linear_velocity = get_global_mouse_position() - global_position
                state.linear_velocity *= mouse_drag_scale
    
by (4,237 points)
edited by

Thanks!

For anyone else reading, I also had to uncheck "can sleep" before it worked for me.

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.