class_name PlayerController extends Node const SPEED = 192.0 @export var dl_map: CombatMap signal combat_requested(attacker: Unit, defender: Unit) var _selected_unit: Unit = null var _target_pos: Vector2 var _goal_pos: Vector2 var _moving := false func _unhandled_input(event: InputEvent) -> void: if event is InputEventMouseButton and not event.pressed and event.button_index == MOUSE_BUTTON_LEFT: var world_pos: Vector2 = get_viewport().get_canvas_transform().affine_inverse() * event.position var clicked_unit := _get_unit_at(world_pos) if clicked_unit: if _selected_unit and clicked_unit != _selected_unit: combat_requested.emit(_selected_unit, clicked_unit) else: _select_unit(clicked_unit) get_viewport().set_input_as_handled() elif _selected_unit: var snapped_pos := dl_map.snap_to_grid(world_pos) var grid_coords := dl_map.world_to_coords(world_pos) if dl_map.is_wall(grid_coords): return _goal_pos = snapped_pos get_viewport().set_input_as_handled() func _physics_process(delta: float) -> void: if not _selected_unit: return if _moving: var remaining := _target_pos - _selected_unit.position var step := SPEED * delta if remaining.length() <= step: _selected_unit.position = _target_pos _moving = false else: _selected_unit.position += remaining.normalized() * step return if _selected_unit.position != _goal_pos: var diff := _goal_pos - _selected_unit.position var dir: Vector2 if absf(diff.x) >= absf(diff.y): dir = Vector2(signf(diff.x), 0) else: dir = Vector2(0, signf(diff.y)) var next_pos := _selected_unit.position + dir * dl_map.TILE_SIZE var grid_coords := dl_map.world_to_coords(next_pos) if dl_map.is_wall(grid_coords): _goal_pos = _selected_unit.position return _target_pos = next_pos _moving = true func _select_unit(unit: Unit) -> void: if _selected_unit: _selected_unit.set_selected(false) _selected_unit = unit _selected_unit.set_selected(true) _goal_pos = _selected_unit.position _target_pos = _selected_unit.position _moving = false func _get_unit_at(world_pos: Vector2) -> Unit: var snapped := dl_map.snap_to_grid(world_pos) for unit: Unit in get_tree().get_nodes_in_group("units"): var unit_snapped := dl_map.snap_to_grid(unit.global_position) if unit_snapped == snapped: return unit return null