Hello.

In my 2D game, while shooting, the cursor position is changed after each shot by the following method:

func get_resolution_ratio():
	return get_viewport().size.x / 800	# Game resolution 800x600

func shot():
	# Part of the method:
	Input.warp_mouse_position(get_viewport().get_mouse_position() * get_resolution_ratio() + Vector2(rand_range(-10 * get_resolution_ratio() * gun_power, 10 * get_resolution_ratio() * gun_power), rand_range(-10 * get_resolution_ratio() * gun_power, 10 * get_resolution_ratio() * gun_power)))

The get_resolution_ratio() method is needed because get_viewport().get_mouse_position() returns the mouse position using the game resolution set in the project settings, while Input.warp_mouse_position() uses the resolution that actually exists at the moment. Because of this, you need to multiply the argument by the ratio of the resolution from the settings and the really existing resolution.

The problem is that it doesn't work correctly, in full screen mode the cursor always moves up and with a much larger step relative to windowed mode (taking into account the difference in resolutions).

Project sources. Used code.

What did I do wrong? Why doesn't it work? Or do you need to decide differently?

  • Megalomaniak
    The problem was due to the difference in the aspect ratio of the monitor and the game (the presence of black bars along the edges of the screen), this problem was solved. Here is the final code, I had to add another method:

    func get_resolution_ratio():
    	return get_viewport().size.x / 800
    
    # Returns the size of the black area from the edge of the screen
    func get_aspect_ratio_difference():
    	if !OS.window_fullscreen:
    		return Vector2(1, 1)
    	
    	if OS.get_screen_size().y == get_viewport().size.y:
    		return Vector2((OS.get_screen_size().x - get_viewport().size.x) / 2, 1)
    	if OS.get_screen_size().x == get_viewport().size.x:
    		return Vector2(1, (OS.get_screen_size().y - get_viewport().size.y) / 2)
    
    func add_recoil():
    	var min_offset_value = -10 * guns_collection[active_gun_number].power
    	var max_offset_value = 10 * guns_collection[active_gun_number].power
    	
    	randomize()
    	var x_offset = rand_range(min_offset_value, max_offset_value)
    	var y_offset = rand_range(min_offset_value, max_offset_value)
    	var offset = Vector2(x_offset, y_offset) * get_resolution_ratio()
    	
    	var real_mouse_position = get_viewport().get_mouse_position() * get_resolution_ratio()
    	var new_mouse_position = real_mouse_position + offset + get_aspect_ratio_difference()
    	Input.warp_mouse_position(new_mouse_position)

    Thank you.

Am I correct in assuming godot version 3.x? I can change the tag if need be.


What exactly are you trying to do with that one extremely long line? Ideally you'd already know the value for the position you want to warp the mouse cursor to. I recommend first splitting that line apart and doing the calculations in a couple of variables ahead of time, might help keep everything more digestible.

That line of code is a future maintenance nightmare just waiting to happen.

    Megalomaniak
    Yes, that's right, I'm using Godot 3.5.1


    I'm trying to move the mouse to a random value based on weapon strength. The multiplication is done to solve the problem with the difference between the values needed for Input.warp_mouse_position() and those returned by get_viewport().get_mouse_position(). Here is the simplified code:

    var min_value = -10 * gun_power
    var max_value = 10 * gun_power
    
    var x_offset = rand_range(min_value, max_value)
    var y_offset = rand_range(min_value, max_value)
    var offset = Vector2(x_offset, y_offset) * get_resolution_ratio()
    
    var real_mouse_position = get_viewport().get_mouse_position() * get_resolution_ratio()
    var new_position = real_mouse_position + offset
    Input.warp_mouse_position(new_position)

    Sometimes refactoring comes to code obfuscation, I'm sorry.

      GREAT-DNG I'm trying to move the mouse to a random value based on weapon strength.

      Is the intended purpose of this to communicate the effect of recoil to the player?

      If so I'd make it a method/function of it's own within the weapon class that can then be called within the weapons fire method as add_recoil(recoil_value) or such.

        Not by itself, but it might get you to a point where the solution becomes obvious. Also makes it easier to analyze if things are more atomized and better structured.

        BTW, to use randomization(rand_range in this case) the randomization has to be initialized somewhere at least once IIRC. Have you done so? Could this be your issue?

        edit: looking at the source linked from OP I do see a ranomize() call in there.

          Megalomaniak
          The problem was due to the difference in the aspect ratio of the monitor and the game (the presence of black bars along the edges of the screen), this problem was solved. Here is the final code, I had to add another method:

          func get_resolution_ratio():
          	return get_viewport().size.x / 800
          
          # Returns the size of the black area from the edge of the screen
          func get_aspect_ratio_difference():
          	if !OS.window_fullscreen:
          		return Vector2(1, 1)
          	
          	if OS.get_screen_size().y == get_viewport().size.y:
          		return Vector2((OS.get_screen_size().x - get_viewport().size.x) / 2, 1)
          	if OS.get_screen_size().x == get_viewport().size.x:
          		return Vector2(1, (OS.get_screen_size().y - get_viewport().size.y) / 2)
          
          func add_recoil():
          	var min_offset_value = -10 * guns_collection[active_gun_number].power
          	var max_offset_value = 10 * guns_collection[active_gun_number].power
          	
          	randomize()
          	var x_offset = rand_range(min_offset_value, max_offset_value)
          	var y_offset = rand_range(min_offset_value, max_offset_value)
          	var offset = Vector2(x_offset, y_offset) * get_resolution_ratio()
          	
          	var real_mouse_position = get_viewport().get_mouse_position() * get_resolution_ratio()
          	var new_mouse_position = real_mouse_position + offset + get_aspect_ratio_difference()
          	Input.warp_mouse_position(new_mouse_position)

          Thank you.