class_name CameraFocusMarker extends Marker2D @export var camera: Camera2D @export_group("Status") @export var lock_horizontal = true @export_group("Config") @export var speed := 5.0 @export var half_screen_size := Vector2(564, 240) / 2.0 @export var shaded_height := 38 @export_group("Shake", "shake_") @export var shake_enabled := false @export var shake_strength := 2.0 @export var shake_recovery_speed := 8.0 @export_group("Limit", "limit_") @export var limit_left := 0.0 @export var limit_right := 564.0 # @export var limit_top := -158.0 # @export var limit_bottom := 158.0 @export var limit_top := 0 @export var limit_bottom := 316.0 @export var zoom_ratio := 1.0 @onready var target = %Target as Node2D var zoom_tween: Tween func _ready() -> void: if not camera: push_error("Camera2D node not found") func tweak_position(velocity, facing_direction): var ideal_x = facing_direction.x * min(50.0, 0.5 * abs(velocity.x)) var current_x = target.position.x var delta = ideal_x - current_x if abs(delta) > 10.0: target.position.x = move_toward(current_x, ideal_x, speed * 2.0) if lock_horizontal: global_position.y = 0 target.position.y = 0 else: target.position.y = facing_direction.y * abs(velocity.y) * 0.2 func _physics_process(delta: float) -> void: if not camera: return # set camera's position var target_position = target.global_position var current_position = camera.global_position # easing with speed var position_delta = (target_position - current_position) * speed * delta var new_position = current_position + position_delta # clamp the position var margin = half_screen_size / zoom_ratio margin.y += shaded_height new_position.x = clamp(new_position.x, limit_left + margin.x, limit_right - margin.x) new_position.y = clamp(new_position.y, limit_top + margin.y, limit_bottom - margin.y) camera.global_position = new_position camera.zoom = Vector2(zoom_ratio, zoom_ratio) func tween_zoom(ratio: float, duration := .7) -> Tween: if zoom_tween and zoom_tween.is_running(): zoom_tween.kill() zoom_tween = create_tween() if duration <= 0.0: zoom_ratio = ratio else: ( zoom_tween . tween_property(self, "zoom_ratio", ratio, duration) . set_trans(Tween.TRANS_CUBIC) . set_ease(Tween.EASE_IN_OUT) ) return zoom_tween var exited := false var exit_position: Vector2 var enter_tree_tween: Tween func _exit_tree() -> void: exit_position = global_position exited = true func _enter_tree() -> void: if exited: if enter_tree_tween and enter_tree_tween.is_running(): enter_tree_tween.kill() exited = false global_position = exit_position enter_tree_tween = create_tween() enter_tree_tween.tween_property(self, "position", Vector2.ZERO, 0.2).set_trans( Tween.TRANS_CUBIC )