Can't get touch Position the right way! HELP

Godot Version

4.3

Question

Hello community! I’m trying my first steps to dev my phone game, and i write this simple code:

func _input(event):
	if event is InputEventScreenDrag:
		global_position = event.position

func _physics_process(delta):
	move_and_slide()

I’m trying that CharacterBody2D (jugador) position snap first touch position when player starts dragging the first touch! But it moves too far from touch center, so it seems that my object has some offsets, i already try to_global(event.position)

In the video below you can see what is happening! I’m totally sure i’m missing something

It looks to me like this is a co-ordinate problem. You are setting a “global position” equal to a “position relative to the viewport”. Global position and position are not the same thing.

As I don’t know how you have setup the rest of you scene, parents nor camera, I am not sure I can help any further but I hope that has helped in some way.

Try printing the global position of your sprite before it is moved and after, as well as the event.position you are receiving and you will see the issue clearly.

I could not find anything better in the docs but here is the position from a screen drag at least.

ok ok, i will try

Main scene tree, everything is in a 0,0 position

Player Scene , everything is in 0,0 position too

i’ve tried position to replace global_position as well and printed the values and i got this:

player position:(0, 0) - touch position:(105, 197)

after a frame:
player position:(105, 197) - touch position:(106, 201)

I can’t understand why i can’t snap the object to touch position! T.T HEEELPPP!!!

The touch position is relative to the screen. So in your case was (105, 197)

The player global position is relative to the world space, in your case (0, 0)

If you print the event (or take a look at the docs) you will see that there are two factors here, the initial touch position and the relative drag position.

func _input(event):
	if event is InputEventScreenDrag:
		print(event)

InputEventScreenDrag: index=0, position=((15, 20)), relative=((1, 0)), velocity=((25.70584, 34.27446)), pressure=1.00, tilt=((0, 0)), pen_inverted=(false)

Have you tried using the relative perhaps? So you could say:

global_position += event.relative

I have not done dragging on mobile but the coordinate transformation should be fairly straight forward, except you will also have to take into account camera zoom if you are changing that. The drag distance is the same, for instance, but if you have zoomed out your transform is different.

Hope that helps in some way.

I may have misunderstood what you were trying to achieve. I think you want the player to ‘snap’ to the touch position. So you need to convert your screen co-ordinates to world co-ordinates, where (0,0) is at the center of the screen.

You can do this with get_viewport something like this:


func _input(event):
	if event is InputEventScreenDrag or event is InputEventScreenTouch:
		var screen_position = event.position
		var canvas_transform = get_viewport().get_canvas_transform()
		var world_position = canvas_transform.affine_inverse() * screen_position
		print("World Position: ", world_position)

Here I touched the top corner and bottom corner of my screen to get these world co-ordinates:

World Position: (5, 7)
World Position: (1140, 635)

Hope that helps. Coordinate transforms can be confusing at first. You will get the hang of it eventually :slight_smile:

1 Like

I think that can be easily solved by dragging the camera top-left to the Vector2(0, 0) position, so the screen position will be the same from the global position of the player

1 Like

Brooo!! this solved it so easy! But i got a bug, it seems that first touch /drag position is always on 0,0 coordinates, so when i start dragging the players moves to 0,0 coordinate first than moves back to touch point,

im using:

position = position.lerp(newpos, 0.5)

where newpos = event.position into _input(event) method

I already fix it with this:

extends CharacterBody2D

var new_pos:Vector2
var touching:bool = false
var cam:Camera2D
var firstFramesTouch:int = 0
func _ready()->void:
	position.x = get_viewport().size.x/2
	new_pos = position #this line fix the bug, avoid going to 0,0 coordinates
	cam = get_tree().current_scene.find_child("Camera2D")
	
func _input(event):
	if event is InputEventScreenDrag:
		new_pos = event.position
		new_pos+=Vector2(0,-200)
		
	if event is InputEventScreenTouch and event.is_pressed():		
		touching=true
	if event is InputEventScreenTouch and event.is_released():
		touching=false

func _process(delta):
	if touching:
		position = position.lerp(new_pos,0.5)
		
	if position.x<cam.position.x+50:
		position.x=cam.position.x+50
		
	if position.x>cam.position.x+get_viewport().size.x-50:
		position.x=cam.position.x+get_viewport().size.x-50
1 Like