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()
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 ! 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()