Cyrille
Cyrille

Reputation: 14533

Holding screen touch in godot

I'm not sure I'm doing things the right way, but I started testing a draft of my 3D game on PC, then I exported it on android.

First, I wanted my player to follow my mouse pointer when I hold the left mouse button down, so I did this :

func _physics_process(delta):
    if Input.is_action_pressed("click"):
        position_2D = get_viewport().get_mouse_position()
        # then, project ray from camera to get a position_3D and move...

Then, when I wanted to convert the mouse button by adding touch screen support on Android, I found InputEventScreenTouch, but I can't find how to use it in _physics_process, so I put everything in _input(event):

func _input(event):
    if event.is_action_pressed("click"):
        position_2D = get_viewport().get_mouse_position()
    elif event is InputEventScreenTouch and event.is_pressed():
        position_2D = get_viewport().get_canvas_transform().affine_inverse().xform(event.position)

The issue is it only detect press event once, so the position is not updated for each frame.

I think I need to put it back in _physics_process, but since I don't have an event instance, I don't know how to do it.

Any pointer? Maybe I'm doing it wrong.

Upvotes: 2

Views: 4811

Answers (1)

Theraot
Theraot

Reputation: 40220

First of all, know that you can emulate mouse input from touch, you will find the option in Project Settings -> Input Devices -> Pointing. It won't do multi-touch, but that is usually the easier way to do it. In particular if you want to keep your _physics_process code.


Anyway, let us talk about handling touch input. You need to be aware of two events: InputEventScreenTouch and InputEventScreenDrag. You are missing the second one. And of course to keep mouse support InputEventMouse (which has two kinds InputEventMouseButton and InputEventMouseMotion).

In fact, I would do this in my code:

if !(event is InputEventScreenDrag)\
and !(event is InputEventScreenTouch)\
and !(event is InputEventMouse):
    return

For multi-touch support, you can distinguish each touch by its index. Except mouse does not have an index. To generalize, we can consider mouse to be index 0, which lead us to this:

var touch_index = 0;
if !(event is InputEventMouse):
    touch_index = event.get_index()

To know if the user is dragging, you can check like this:

var is_drag = event is InputEventScreenDrag or event is InputEventMouseMotion

If it is not a drag, it is either a press or a release event. You can distinguish those two by checking event.is_pressed(). I need to reiterate, event.is_pressed() is only relevant when is_drag is false. Let me put it this way:

var is_drag = event is InputEventScreenDrag or event is InputEventMouseMotion
var is_press = !is_drag and event.is_pressed()
var is_release = !is_drag and !event.is_pressed()

By the way, for the mouse, you can use button_mask to figure out which buttons are pressed. For example:

var is_left_click = event is InputEventMouse\
                    and ((event as InputEventMouse).button_mask & BUTTON_LEFT) != 0

You may want to add that logic to is_press if you only want left click to count, for example.

And finally for the position event.position works, even for mouse. And if you want the position in the local coordinates of some CanvasItem (Node2D or Control), you can use make_input_local.

Upvotes: 2

Related Questions