I need help to recreate Link's Awakening rotation

Godot Version

4.5 stable

Question

How can I reproduce the way Link rotates, like in the video below, while using a gamepad ?

Hello everyone ! I would like to make my top-down player to rotate with an increment of 45 degrees with a gamepad,
exactly as this :
Link’s Awakening Switch

As of now, i’ve started implementing something, but it turns out to be a complete mess:


extends CharacterBody3D


func _physics_process(_delta: float) -> void:
        # Get Inputs
	var input_vector = Vector3.ZERO
	input_vector.x = Input.get_action_strength(&"right") - Input.get_action_strength(&"left")
	input_vector.z = Input.get_action_strength(&"down") - Input.get_action_strength(&"up")


	# Move on 8 directions
	var _angle: float = rad_to_deg(Vector2(velocity.x, velocity.z).angle())

	velocity = input_vector.normalized() * 1.5

	if input_vector.length() > 0.0:
		var _target_angle: float
		print(_angle)

		if _angle < 22.5 and _angle > -22.5: # RIGHT
			_target_angle = -90.0
		elif _angle < -67.5 and _angle > -112.5: # UP
			_target_angle = 0.0
		elif _angle < 112.5 and _angle > 67.5: # DOWN
			_target_angle = 180.0
		elif _angle < 157.5 and _angle > -157.5: # LEFT
			_target_angle = 90.0


		mesh_instance.rotation_degrees.y = _target_angle

	move_and_slide()

Can you help me please ?

Okay, so you want to limit the movement and mesh rotation to 8 directions? I think something like that should work:

extends CharacterBody3D


func _physics_process(_delta: float) -> void:
	
	# Get Inputs as Vector2
	var input_vector := Input.get_vector("left", "right", "up", "down")
	
	# Move on 8 directions
	var _angle: float = input_vector.angle() ## in radians
	_angle = snapped(_angle, deg_to_rad(45.0)) # snaps angle to the closest 45° direction
	var _snapped_vector := Vector2.RIGHT.rotated(_angle) ## new Vector2 in the snapped direction
	
	velocity = Vector3(_snapped_vector.x, 0, _snapped_vector.y) * input_vector.length() * 1.5
	
	# Rotate the mesh
	# (this might need some offset like '+ deg_to_rad(90.0)' or so)
	mesh_instance.rotation.y = _angle
	
	move_and_slide()

(I haven’t tested this, so I hope there aren’t any grave mistakes in it.)

Thank you so much :rofl: ! It’s working perfectly. I just had to adjust the mesh_instance Y rotation since it faces -Z axis by default, as well as the velocity, to get a more “free” movement

This is the final code :

extends CharacterBody3D

func _physics_process(_delta: float) -> void:
	# Get Inputs as Vector2
	var input_vector := Input.get_vector("left", "right", "up", "down")

	# Move on 8 directions
	var _angle: float = input_vector.angle() ## in radians
	_angle = snapped(_angle, deg_to_rad(45.0)) # snaps angle to the closest 45° direction
	var _snapped_vector := Vector2.RIGHT.rotated(_angle) ## new Vector2 in the snapped direction

	#velocity = Vector3(_snapped_vector.x, 0, _snapped_vector.y) * input_vector.length() * 1.5
	velocity = Vector3(input_vector.x, 0.0, input_vector.y) * 2.5

	# Rotate the mesh
	# (this might need some offset like '+ deg_to_rad(90.0)' or so)
    if input_vector.length() != 0.0:
	    mesh_instance.rotation.y = -_angle - deg_to_rad(90.0)

	move_and_slide()
1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.