Help with smooth Vector2 movement

Godot Version

4.2.2 Stable

Question

I made a 2d shooter, and gave my player this recoil effect whenever I shoot. The player is moved slightly based on the mouse cursor. However, the movement is way to sudden. I want to smoothen it a little bit to make it more realistic. But I don’t know how. It’s one of the first times working with Vector2s this way(normally, I would do speed * 0.9 or something like that), so help is highly appreciated.

func move_player_away_from_cursor(length):
	var player_position = global_position
	var mouse_position = get_global_mouse_position()
	var direction_to_mouse = (mouse_position - player_position).normalized()
	var move_away_vector = -direction_to_mouse * length  # Adjust the multiplier as needed
	
	# Update the player's position
	global_position += move_away_vector

You could use a tween, though it will be very rigid. is your player a physics body like CharacterBody2D? Try adding the kick back to velocity, and avoid outright setting velocity elsewhere; instead using move_toward when possible.

Ok, so I updated the script to something like this(and yes, I use a chracterbody2d):

func move_player_away_from_cursor(length):
	var direction_to_mouse = (get_global_mouse_position() - global_position).normalized()
	
	velocity += -direction_to_mouse * length
	
	move_and_slide()

This worked, and it’s easier to read but there’s not smoothness yet.

What you need is a lerp from the current velocity to the desired velocity.

How exactly would I do that? I have tried to implement it, but it would interfere with the movement of my player.

velocity = velocity.lerp(velocity -direction_to_mouse * length)

This should work

i got this warning:

Too few arguments for “lerp()” call. Expected at least 2 but received 1.

func move_player_away_from_cursor(length):
	var direction_to_mouse = (get_global_mouse_position() - global_position).normalized()
	
	velocity += -direction_to_mouse * length
	velocity = velocity.lerp(velocity -direction_to_mouse * length)
	
	move_and_slide()

Also, the function is only called once a while. Maybe I should make it go continuously, and add a variable for when it should be active and when not?

My mistake, there is a second float value called weight. The weight to set the interpolation.

Adding a booleab to determine when it should be called is exactly what you should do. I also want to assume you’re calling the move_player_away_from_cursor function from physics process right?

Alright, will try that. In the current script, I’m not running it from the physics process, but I will fix that.

1 Like

Alright, I did like you suggested and it works great :upside_down_face: thx
Here’s the code incase someone wants to see:

func _process(delta):
	
	if gun_select == "gun":
		if Input.is_action_pressed("shoot"):
			recoil = true
		else:
			recoil = false

	move_player_away_from_cursor(50)

func move_player_away_from_cursor(length):
	if recoil == true:
		var direction_to_mouse = (get_global_mouse_position() - global_position).normalized()
		
		velocity += -direction_to_mouse * length
		velocity = velocity.lerp(velocity -direction_to_mouse * length, 5)
		
		move_and_slide()

I’m sure you could clean it up a little bit, but it works and thats all that matters right now.

1 Like