2025-01-21 13:49:37 +00:00
|
|
|
class_name CameraFocusMarker extends Camera2D
|
2024-12-23 01:29:31 +00:00
|
|
|
|
2025-01-21 13:49:37 +00:00
|
|
|
@export var focusing_node: Node2D
|
|
|
|
@export var force_offset := Vector2.ZERO
|
2025-01-03 08:07:35 +00:00
|
|
|
@export_group("Status")
|
2024-12-26 13:58:37 +00:00
|
|
|
@export var lock_horizontal = true
|
2025-01-03 08:07:35 +00:00
|
|
|
@export_group("Config")
|
|
|
|
@export var speed := 5.0
|
2025-01-02 11:01:44 +00:00
|
|
|
@export var half_screen_size := Vector2(564, 240) / 2.0
|
2025-01-03 08:07:35 +00:00
|
|
|
@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
|
2025-01-21 13:49:37 +00:00
|
|
|
# @export_group("Limit", "limit_")
|
|
|
|
# @export var limit_left := 0.0
|
|
|
|
# @export var limit_right := 564.0
|
|
|
|
# @export var limit_top := 0
|
|
|
|
# @export var limit_bottom := 316.0
|
2025-01-21 10:08:16 +00:00
|
|
|
@export var zoom_ratio := 1.0
|
2025-01-02 11:01:44 +00:00
|
|
|
|
2025-01-21 13:49:37 +00:00
|
|
|
var _tweeked_position := Vector2.ZERO
|
2025-01-02 11:01:44 +00:00
|
|
|
|
2025-01-03 08:07:35 +00:00
|
|
|
var zoom_tween: Tween
|
2025-01-21 13:49:37 +00:00
|
|
|
var zooming_and_focus_start_position: Vector2
|
|
|
|
# 0 to 1
|
|
|
|
var zooming_and_focus_progress := 1.0
|
2025-01-02 11:01:44 +00:00
|
|
|
|
|
|
|
|
2025-01-16 12:24:21 +00:00
|
|
|
func _ready() -> void:
|
2025-01-21 13:49:37 +00:00
|
|
|
if not focusing_node:
|
|
|
|
push_error("Focusing node not found")
|
|
|
|
|
|
|
|
|
|
|
|
func reset_position_immediately():
|
|
|
|
if focusing_node:
|
|
|
|
global_position = focusing_node.global_position + _tweeked_position + force_offset
|
2025-01-16 12:24:21 +00:00
|
|
|
|
|
|
|
|
2024-12-23 13:04:36 +00:00
|
|
|
func tweak_position(velocity, facing_direction):
|
2025-01-03 08:07:35 +00:00
|
|
|
var ideal_x = facing_direction.x * min(50.0, 0.5 * abs(velocity.x))
|
2025-01-21 13:49:37 +00:00
|
|
|
var current_x = _tweeked_position.x
|
2025-01-03 08:07:35 +00:00
|
|
|
var delta = ideal_x - current_x
|
|
|
|
if abs(delta) > 10.0:
|
2025-01-21 13:49:37 +00:00
|
|
|
_tweeked_position.x = move_toward(current_x, ideal_x, speed * 2.0)
|
2024-12-26 13:58:37 +00:00
|
|
|
if lock_horizontal:
|
|
|
|
global_position.y = 0
|
2025-01-21 13:49:37 +00:00
|
|
|
_tweeked_position.y = 0
|
2024-12-26 13:58:37 +00:00
|
|
|
else:
|
2025-01-21 13:49:37 +00:00
|
|
|
_tweeked_position.y = facing_direction.y * abs(velocity.y) * 0.2
|
2025-01-02 11:01:44 +00:00
|
|
|
|
|
|
|
|
|
|
|
func _physics_process(delta: float) -> void:
|
|
|
|
# set camera's position
|
2025-01-21 13:49:37 +00:00
|
|
|
var target_position = focusing_node.global_position + _tweeked_position + force_offset
|
|
|
|
if focusing_node is MainPlayer:
|
|
|
|
# player 的焦点在脚底,所以需要加上 player 的高度
|
|
|
|
# 注意方向向下,负数
|
|
|
|
target_position.y -= focusing_node.current_animation_config.os_height * 0.7
|
|
|
|
# 如果有 zooming_and_focus_progress, 将其位置加入计算
|
|
|
|
if zooming_and_focus_progress < 1.0:
|
|
|
|
target_position.x = lerpf(
|
|
|
|
zooming_and_focus_start_position.x, target_position.x, zooming_and_focus_progress
|
|
|
|
)
|
|
|
|
target_position.y = lerpf(
|
|
|
|
zooming_and_focus_start_position.y, target_position.y, zooming_and_focus_progress
|
|
|
|
)
|
2025-01-02 11:01:44 +00:00
|
|
|
# easing with speed
|
2025-01-21 13:49:37 +00:00
|
|
|
var new_position = global_position + (target_position - global_position) * speed * delta
|
2025-01-02 11:01:44 +00:00
|
|
|
# clamp the position
|
|
|
|
var margin = half_screen_size / zoom_ratio
|
2025-01-03 08:07:35 +00:00
|
|
|
margin.y += shaded_height
|
2025-01-02 11:01:44 +00:00
|
|
|
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)
|
2025-01-21 13:49:37 +00:00
|
|
|
global_position = new_position
|
|
|
|
zoom = Vector2(zoom_ratio, zoom_ratio)
|
2025-01-02 11:01:44 +00:00
|
|
|
|
|
|
|
|
2025-01-21 13:49:37 +00:00
|
|
|
func tween_zoom(ratio: float, duration := 1.5, refocus := false):
|
2025-01-03 08:07:35 +00:00
|
|
|
if zoom_tween and zoom_tween.is_running():
|
|
|
|
zoom_tween.kill()
|
|
|
|
zoom_tween = create_tween()
|
2025-01-21 13:49:37 +00:00
|
|
|
(
|
|
|
|
zoom_tween
|
|
|
|
. tween_property(self, "zoom_ratio", ratio, duration)
|
|
|
|
. set_trans(Tween.TRANS_CUBIC)
|
|
|
|
. set_ease(Tween.EASE_IN_OUT)
|
|
|
|
)
|
|
|
|
if refocus:
|
|
|
|
zooming_and_focus_start_position = global_position
|
2025-01-06 08:06:20 +00:00
|
|
|
(
|
|
|
|
zoom_tween
|
2025-01-21 13:49:37 +00:00
|
|
|
. parallel()
|
|
|
|
. tween_property(self, "zooming_and_focus_progress", 1.0, duration)
|
|
|
|
. from(0.0)
|
|
|
|
. set_trans(Tween.TRANS_LINEAR)
|
2025-01-06 08:06:20 +00:00
|
|
|
. set_ease(Tween.EASE_IN_OUT)
|
|
|
|
)
|
2025-01-16 12:24:21 +00:00
|
|
|
|
|
|
|
|
2025-01-21 13:49:37 +00:00
|
|
|
func focus_node(node: Node2D) -> void:
|
|
|
|
focusing_node = node
|
2025-01-16 12:24:21 +00:00
|
|
|
|
2025-01-21 13:49:37 +00:00
|
|
|
# var exited := false
|
|
|
|
# var exit_position: Vector2
|
|
|
|
# var enter_tree_tween: Tween
|
2025-01-16 12:24:21 +00:00
|
|
|
|
2025-01-21 13:49:37 +00:00
|
|
|
# func _exit_tree() -> void:
|
|
|
|
# exit_position = global_position
|
|
|
|
# exited = true
|
2025-01-16 12:24:21 +00:00
|
|
|
|
2025-01-21 13:49:37 +00:00
|
|
|
# func _enter_tree() -> void:
|
|
|
|
# if exited and is_node_ready():
|
|
|
|
# exited = false
|
|
|
|
# if enter_tree_tween and enter_tree_tween.is_running():
|
|
|
|
# enter_tree_tween.kill()
|
|
|
|
# enter_tree_tween = create_tween()
|
|
|
|
# global_position = exit_position
|
|
|
|
# enter_tree_tween.tween_property(self, "position", Vector2.ZERO, 0.2).set_trans(
|
|
|
|
# Tween.TRANS_CUBIC
|
|
|
|
# )
|