mirror of
https://github.com/godotengine/godot-demo-projects.git
synced 2025-12-16 05:20:06 +01:00
75 lines
1.9 KiB
GDScript
75 lines
1.9 KiB
GDScript
extends Node2D
|
|
|
|
|
|
const PathFindAStar = preload("./pathfind_astar.gd")
|
|
|
|
enum State {
|
|
IDLE,
|
|
FOLLOW,
|
|
}
|
|
|
|
const MASS: float = 10.0
|
|
const ARRIVE_DISTANCE: float = 10.0
|
|
|
|
@export_range(10, 500, 0.1, "or_greater") var speed: float = 200.0
|
|
|
|
var _state := State.IDLE
|
|
var _velocity := Vector2()
|
|
|
|
var _click_position := Vector2()
|
|
var _path := PackedVector2Array()
|
|
var _next_point := Vector2()
|
|
|
|
@onready var _tile_map: PathFindAStar = $"../TileMapLayer"
|
|
|
|
|
|
func _ready() -> void:
|
|
_change_state(State.IDLE)
|
|
|
|
|
|
func _physics_process(_delta: float) -> void:
|
|
if _state != State.FOLLOW:
|
|
return
|
|
|
|
var arrived_to_next_point: bool = _move_to(_next_point)
|
|
if arrived_to_next_point:
|
|
_path.remove_at(0)
|
|
if _path.is_empty():
|
|
_change_state(State.IDLE)
|
|
return
|
|
_next_point = _path[0]
|
|
|
|
|
|
func _unhandled_input(input_event: InputEvent) -> void:
|
|
_click_position = get_global_mouse_position()
|
|
if _tile_map.is_point_walkable(_click_position):
|
|
if input_event.is_action_pressed(&"teleport_to", false, true):
|
|
_change_state(State.IDLE)
|
|
global_position = _tile_map.round_local_position(_click_position)
|
|
reset_physics_interpolation()
|
|
elif input_event.is_action_pressed(&"move_to"):
|
|
_change_state(State.FOLLOW)
|
|
|
|
|
|
func _move_to(local_position: Vector2) -> bool:
|
|
var desired_velocity: Vector2 = (local_position - position).normalized() * speed
|
|
var steering: Vector2 = desired_velocity - _velocity
|
|
_velocity += steering / MASS
|
|
position += _velocity * get_physics_process_delta_time()
|
|
rotation = _velocity.angle()
|
|
return position.distance_to(local_position) < ARRIVE_DISTANCE
|
|
|
|
|
|
func _change_state(new_state: State) -> void:
|
|
if new_state == State.IDLE:
|
|
_tile_map.clear_path()
|
|
elif new_state == State.FOLLOW:
|
|
_path = _tile_map.find_path(position, _click_position)
|
|
if _path.size() < 2:
|
|
_change_state(State.IDLE)
|
|
return
|
|
# The index 0 is the starting cell.
|
|
# We don't want the character to move back to it in this example.
|
|
_next_point = _path[1]
|
|
_state = new_state
|