优化相机移动问题,丝滑运镜

This commit is contained in:
cakipaul 2025-07-06 04:10:18 +08:00
parent 1c2fc4fb70
commit 2f5e2128e3
10 changed files with 70 additions and 52 deletions

View File

@ -9,7 +9,7 @@ keys,zh_CN,en
方启钊,方启钊,"Fang Qizhao"
方小蝉,方小蝉,"Fang Xiaochan"
小男孩,小男孩,"Little Boy"
小蝉,小蝉,"Little Cicada"
小蝉,小蝉,"Little Chan"
男孩黄,男孩黄,"Boy in Yellow"
男孩蓝,男孩蓝,"Boy in Blue"
小肉圆,小肉圆,"Pudgy"

1 keys zh_CN en
9 方启钊 方启钊 Fang Qizhao
10 方小蝉 方小蝉 Fang Xiaochan
11 小男孩 小男孩 Little Boy
12 小蝉 小蝉 Little Cicada Little Chan
13 男孩黄 男孩黄 Boy in Yellow
14 男孩蓝 男孩蓝 Boy in Blue
15 小肉圆 小肉圆 Pudgy

View File

@ -69,13 +69,12 @@ func focus_node(node: Node2D, duration := 0.0) -> void:
marker.focus_node(node, duration)
func focus_player_and_reset_zoom(duration := 1.2) -> void:
func focus_player_and_reset_zoom(duration := 1.0) -> void:
var marker = get_camera_marker()
if marker:
# marker.force_offset = Vector2.ZERO
# 延长可更丝滑
marker.tween_zoom(1.0, duration)
# 运镜更平滑一些
marker.focus_node(get_player(), duration + .3)
marker.focus_node(get_player(), duration)
func get_lock() -> PlayerReenterLock:

View File

@ -164,11 +164,11 @@ func _do_action() -> void:
status = STATUS_TRANSITIONING
icount += 1
sfx.play()
SceneManager.focus_node(self)
SceneManager.get_camera_marker().tween_zoom(2.0)
SceneManager.focus_node(self, 0.5)
SceneManager.get_camera_marker().tween_zoom(1.5, 1.2)
var tween = create_tween()
tween.tween_interval(0.8)
tween.tween_property(container, "modulate:a", 1.0, 0.7)
tween.tween_interval(0.5)
tween.tween_property(container, "modulate:a", 1.0, 0.8)
tween.tween_callback(func(): status = STATUS_INSPECTING_COVER)
# 改变信号源
sign_mark.interacted.connect(_on_interacted)

View File

@ -155,6 +155,6 @@ layout_mode = 2
size_flags_horizontal = 4
size_flags_vertical = 8
theme_override_fonts/font = ExtResource("7_ianbs")
text = "Q: Exit E: Read"
text = "Q: ui_退出 E: ui_阅读"
horizontal_alignment = 1
vertical_alignment = 1

View File

@ -122,7 +122,6 @@ func _show_os():
func _show_balloon(res, title):
# SceneManager.focus_node(self)
DialogueManager.show_dialogue_balloon(res, title)
# note viewing animation
SceneManager.lock_player(0, action)

View File

@ -4,9 +4,6 @@ class_name CameraFocusMarker extends Camera2D
@export var force_offset := Vector2.ZERO
# @export_group("Status")
# @export var lock_horizontal = true
@export_group("Config")
@export var half_screen_size := Vector2(564, 240) / 2.0
@export var shaded_height := 38
@export_group("Shake", "shake_")
@export var shake_strength := 0.0
@export var shake_recovery_speed := 4.0
@ -16,7 +13,6 @@ var speed := 2.0
var _tweeked_position := Vector2.ZERO
var zoom_tween: Tween
var _focus_offset := Vector2.ZERO
var shake_ignore_boundary := false
@ -33,7 +29,7 @@ func shake_camera(strength := 6.0, recovery_speed := 2.0, ignore_boundary := tru
func reset_position_immediately():
if focusing_node:
progressing_position = focusing_node.global_position + _tweeked_position + force_offset
progressing_position = (focusing_node.global_position + _tweeked_position + force_offset)
global_position = progressing_position
print("CameraFocusMarker reset_position_immediately to:", global_position)
@ -45,10 +41,10 @@ func tweak_position(velocity, facing_direction):
if abs(delta) > 10.0:
_tweeked_position.x = move_toward(current_x, ideal_x, speed * 2.0)
# if lock_horizontal:
# global_position.y = 0
# _tweeked_position.y = 0
# global_position.y = 0
# _tweeked_position.y = 0
# else:
# _tweeked_position.y = facing_direction.y * abs(velocity.y) * 0.2
# _tweeked_position.y = facing_direction.y * abs(velocity.y) * 0.2
# 处理过程的当下理想位置
@ -72,6 +68,7 @@ func _physics_process(delta: float) -> void:
# handle shake
if shake_strength > 0.0:
# 让 shake_strength 逐帧衰减
shake_recovery_speed = min(0.1, shake_recovery_speed)
shake_strength = lerpf(shake_strength, 0.0, shake_recovery_speed * delta)
# [-shake_strength, +shake_strength] 范围内的同时,尽可能偏离中心
# 在 0 2π 之间随机一个方向,在 _last_shake_angle 的对角范围
@ -93,9 +90,13 @@ func _physics_process(delta: float) -> void:
zoom = Vector2(zoom_ratio, zoom_ratio)
var half_screen_size := Vector2(564, 240) / 2.0
var shading_y := 38.0
func _clamp_boundary(target: Vector2) -> Vector2:
var margin = half_screen_size / zoom_ratio
margin.y += shaded_height
margin.y += shading_y
target.x = clamp(target.x, limit_left + margin.x, limit_right - margin.x)
target.y = clamp(target.y, limit_top + margin.y, limit_bottom - margin.y)
return target
@ -134,33 +135,13 @@ func focus_node(node: Node2D, duration := 0.0) -> void:
focusing_node = null
return
if duration > 0.0:
_focus_offset = global_position - node.global_position
if tween_focus and tween_focus.is_running():
tween_focus.kill()
tween_focus = create_tween()
(
tween_focus
. tween_property(self, "_focus_offset", Vector2.ZERO, duration)
. set_trans(Tween.TRANS_SINE)
. set_ease(Tween.EASE_IN_OUT)
)
tween_focus.tween_method(_update_focus_progress, 0.0, 1.0, duration)
_update_focus_progress(0.0)
focusing_node = node
# 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 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
# )
func _update_focus_progress(progress: float):
speed = 0.2 + 1.8 * smoothstep(0.0, 1.0, progress)

View File

@ -90,15 +90,15 @@ func _dean_flip_book() -> void:
func pre_game_intro():
SceneManager.lock_player()
var camera = SceneManager.get_camera_marker() as CameraFocusMarker
camera.tween_zoom(1.5, 3.0)
camera.tween_zoom(1.5, 3.5)
var p = $"../DeployLayer/四小孩画鬼差的对话ambush/FocusPoint"
camera.focus_node(p, 3.0)
await Util.wait(1.5)
await Util.wait(2.0)
DialogueManager.show_dialogue_balloon(dialogue_c01, "c01_s06_四个小孩画鬼差的对话")
await DialogueManager.dialogue_ended
# 重置镜头
SceneManager.focus_player_and_reset_zoom(2.5)
await Util.wait(1.5)
await Util.wait(2.5)
await SceneManager.pop_os_with_str("c01_s06_熟悉的墙画")
SceneManager.unlock_player()

View File

@ -139,6 +139,7 @@ animations = [{
}]
[node name="S06" type="Node2D"]
position = Vector2(-1, 0)
metadata/_edit_horizontal_guides_ = [158.0, 91.0, 81.0]
[node name="Ground" parent="." instance=ExtResource("1_bitx7")]

View File

@ -55,16 +55,12 @@ func _on_ground_ready() -> void:
func intro() -> void:
begger.play("杂戏团夜晚_小孩举碗呼吸")
# SceneManager.freeze_player(0)
# SceneManager.focus_node(begger, 5.)
# SceneManager.focus_node(begger, 5.0)
Util.timer(1., _intro_dialog)
func _intro_dialog() -> void:
DialogueManager.show_dialogue_balloon(dialogue_c01, "c01_s12_诡异的书店外发钱")
# DialogueManager.dialogue_ended.connect(_on_intro_dialogue_ended, CONNECT_ONE_SHOT)
# func _on_intro_dialogue_ended(_res) -> void:
# SceneManager.focus_player_and_reset_zoom(5.)
# SceneManager.release_player()
func ambush_begger_interacted():

View File

@ -19,6 +19,48 @@
}
}
},
"c01_s06_孤儿院长廊围墙": {
"global": {
"enabled_items": {},
"player_x": 1300.0
},
"ground": {
&"AnimationPlayer": {},
&"Interactable桌椅": {
"interacted_times": 0
},
&"四小孩画鬼差的对话ambush": {
"played": false
},
&"桌椅ambush1": {
"played": false
},
&"桌椅ambush2": {
"played": false
},
&"桌椅ambush3": {
"played": false
},
&"猫鼠游戏失败ambush": {
"played": false
},
&"猫鼠游戏开始ambush": {
"played": false
},
&"猫鼠游戏胜利ambush": {
"played": false
},
&"猫鼠游戏重置ambush": {
"played": false
},
&"门口ambush": {
"played": false
},
&"门口对话ambush": {
"played": false
}
}
},
"c01_s08_书店": {
"global": {
"c01_shelf_game_success": false,