Godot Version
4.2
Question
The summary of this question is: How do I add a turn radius to point-&-click movement, and is a NavigationRegion2D the best choice for what I’m trying to do? I’m happy to just be pointed towards some resources, as my searches have not been very successful.
Game system is a top-down 2D multiplayer space game, basically a mostly open plane with the occasional small obstacle. I am developing this at the request of a friend, taking the project on as something of a challenge for myself, so switching to wasd movement would be undesirable. I’ve already told him that I almost certainly will not be making an entire end-product game for him, but I would like to try and deliver on a basic concept (end goal = multiple players in a server that can “mine” asteroids and attack each other).
The first hurdle I have reached is my friend’s rather specific vision for movement. He is adamant that the game be point-&-click, but also wants ships to have variable maneuverability based on engine stats. Currently I’m not really worried about the engine stats, I’m having enough trouble just trying to implement point-&-click that isn’t moving in a straight line.
All navigation systems I have found through tutorials give the character no turn radius, you simply gain velocity directly towards the target location and the sprite adjusts to match. I am looking for a system where the character only moves in the direction it is facing, and instead curves towards the destination (curve radius would later be determined by ship engine stats).
Is NavigationServer/Region2D even the correct choice for this? Do I need to be defining my own pathfinding if I want this style of movement, or is there another option that I haven’t run into?
Below is the relevant portions of my current attempt at emulating this:
const BASE_SPEED = 400
var acceleration = 1 # Too floaty, overshoots target
func _ready():
navigation_agent.path_desired_distance = 35.0 # Just messing with the numbers here
navigation_agent.target_desired_distance = 30.0
func _physics_process(delta):
if navigation_agent.is_navigation_finished():
return
var current_agent_position: Vector2 = global_position
var next_path_position: Vector2 = navigation_agent.get_next_path_position()
# Issue here is that the path is a straight line to target position
# velocity should maybe be determined by orientation instead of the other way around?
var direction = current_agent_position.direction_to(next_path_position)
velocity = velocity.lerp(direction * BASE_SPEED, acceleration * delta)
rotation_degrees = determine_orientation(velocity)
move_and_slide()
func determine_orientation(pos: Vector2):
var face = atan2(pos.y,pos.x) * 180/PI
return face
func set_movement_target(movement_target: Vector2):
navigation_agent.target_position = movement_target
func _input(event):
if event.is_action_pressed("left_click"):
set_movement_target(get_global_mouse_position())
My next step was going to be to implement it as “turn first, then move to position”, and then try to convert that into turning and moving at the same time.