Search code examples
godotgdscript

my get_viewport().get_mouse_position() isn't working right godot GDscript


I'm trying to make a 2d platformer where you spawn an object and try to jump on it in the air before it falls.

the problem is when I try to spawn the tile it doesn't spawn where Is the cursor at it adds a relative value to the position that I don't know how to get rid of it.

you see when I try to instance a scene it takes the cursor position and viewport value into account but then something happens and I fount the object spawning way too far.

see where is the cursor at and where did the tile spawn

, same thing here

, and here

-here is how I'm grouping the nodes and scenes-

and this is the script I'm using, it's in the player1 scene

extends KinematicBody2D
# 
var score : int = 0

export var speed : int = 200
export var jumpforce : int = 600
export var gravity : int = 800

onready var AB1 = preload("res://player1AB.tscn")

var vel :Vector2 = Vector2()

onready var sprite : Sprite = get_node("sprite_idile")
onready var ui : Node = get_node("/root/mainscene1/CanvasLayer/ui")
onready var audioplayer : Node = get_node("/root/mainscene1/Camera2D/audio_player")

func _physics_process(delta):
    vel.x = 0
    # movement inputs
    if Input.is_action_pressed("move_left"):
        vel.x -= speed

    if Input.is_action_pressed("move_right"):
        vel.x += speed

    # applying the velcoty
    vel = move_and_slide(vel,Vector2.UP)

    #apllying gravty
    vel.y += gravity * delta

    #jump input
    if Input.is_action_just_pressed("jump") and is_on_floor():
        vel.y -= jumpforce

    # where the sprite facing
        if vel.x < 0:
        sprite.flip_h = true
    if vel.x > 0:
        sprite.flip_h = false

    if Input.is_action_just_pressed("restart"):
        death()



func death ():
    get_tree().reload_current_scene()



func collect_coin (value):
    score += value
    ui.set_score_text(score)
    audioplayer.play_coin_sfx()


func _input(event):
    if event.is_action_pressed("click"):
        var ABT1 = AB1.instance()
        add_child(ABT1)
        var XN = null
        XN = get_viewport().get_mouse_position()  
        ABT1.position = XN

important stuff

onready var AB1 = preload("res://player1AB.tscn")



func _input(event):
    if event.is_action_pressed("click"):
        var ABT1 = AB1.instance()
        add_child(ABT1)
        var XN = null
        XN = get_viewport().get_mouse_position()  
        ABT1.position = XN

this the same problem in Godot form check it out if possible in case someone answered there

https://godotforums.org/discussion/27007/my-get-viewport-get-mouse-position-isnt-working-right#latest


Solution


  • If you don't have an extra Viewport

    My first intuition is to get get_global_mouse_position and set global_position. That way you don't have to deal with any relative positioning:

        ABT1.global_position = get_global_mouse_position() 
    

    Alternatively, you can check if the event is InputEventMouse, make it local with make_input_local, and get InputEventMouse.position from it:

    func _input(event):
        if event is InputEventMouse and event.is_action_pressed("click"):
    
            var ABT1 = AB1.instance()
            add_child(ABT1)
    
            event = make_input_local(event)
            ABT1.position = event.position
    

    This approach would make it easier to then add touch support, because it does not rely on any function that gives you the mouse position. See my answer for Holding screen touch in godot.


    If you have an extra Viewport

    First of all, make sure you put your Viewport inside a ViewportContainer (otherwise it does not get input, see _input not called for a node inside a Viewport). Then we can use that ViewportContainer to get our coordinates.

    Something like this:

    func _input(event):
        if event is InputEventMouse and event.is_action_pressed("click"):
    
            var ABT1 = AB1.instance()
            add_child(ABT1)
    
            var container = find_parent("ViewportContainer") as ViewportContainer
            if container != null:
                event = container.make_input_local(event)
    
            event = make_input_local(event)
            ABT1.position = event.position
    

    Notice there I'm using the function find_parent. It matches by name of the Node, not by type. Another approach you can try is using get_viewport().get_parent().

    And yes, that should work regardless of stretch mode.