优化相机移动:在 focus 过程中增加平滑感

This commit is contained in:
cakipaul 2025-01-31 19:21:41 +08:00
parent a42fa8ae73
commit 64b1725241
10 changed files with 59 additions and 53 deletions

View File

@ -223,7 +223,7 @@ animations = [{
"duration": 3.0, "duration": 3.0,
"texture": ExtResource("37_u6xcr") "texture": ExtResource("37_u6xcr")
}], }],
"loop": true, "loop": false,
"name": &"男孩跑动停球", "name": &"男孩跑动停球",
"speed": 30.0 "speed": 30.0
}, { }, {
@ -366,7 +366,7 @@ animations = [{
"duration": 6.0, "duration": 6.0,
"texture": ExtResource("73_8tjai") "texture": ExtResource("73_8tjai")
}], }],
"loop": true, "loop": false,
"name": &"院长翻书", "name": &"院长翻书",
"speed": 30.0 "speed": 30.0
}] }]

View File

@ -40,10 +40,10 @@ func get_player() -> MainPlayer:
return null return null
func focus_node(node: Node2D) -> void: func focus_node(node: Node2D, duration := 0.0) -> void:
var marker = get_camera_marker() var marker = get_camera_marker()
if marker: if marker:
marker.focus_node(node) marker.focus_node(node, duration)
func focus_player_and_reset_zoom(duration := 1.2) -> void: func focus_player_and_reset_zoom(duration := 1.2) -> void:
@ -51,7 +51,8 @@ func focus_player_and_reset_zoom(duration := 1.2) -> void:
if marker: if marker:
# marker.force_offset = Vector2.ZERO # marker.force_offset = Vector2.ZERO
marker.tween_zoom(1.0, duration) marker.tween_zoom(1.0, duration)
marker.focus_node(get_player()) # 运镜更平滑一些
marker.focus_node(get_player(), duration + .3)
# action_locked 用于设置界面等强制锁定action_freezed 用于查看物品等锁定 # action_locked 用于设置界面等强制锁定action_freezed 用于查看物品等锁定

View File

@ -17,14 +17,12 @@ class_name CameraFocusMarker extends Camera2D
# @export var limit_top := 0 # @export var limit_top := 0
# @export var limit_bottom := 316.0 # @export var limit_bottom := 316.0
@export var zoom_ratio := 1.0 @export var zoom_ratio := 1.0
var speed := 5.0 var speed := 3.0
var _tweeked_position := Vector2.ZERO var _tweeked_position := Vector2.ZERO
var zoom_tween: Tween var zoom_tween: Tween
# var zooming_and_focus_start_position: Vector2 var focus_offset := Vector2.ZERO
# # 0 to 1
# var zooming_and_focus_progress := 1.0
func _ready() -> void: func _ready() -> void:
@ -57,28 +55,27 @@ func tweak_position(velocity, facing_direction):
func _physics_process(delta: float) -> void: func _physics_process(delta: float) -> void:
if not focusing_node:
return
# set camera's position # set camera's position
var target_position = focusing_node.global_position + _tweeked_position + force_offset var target_position = (
focusing_node.global_position + _tweeked_position + force_offset + focus_offset
)
if focusing_node is MainPlayer: if focusing_node is MainPlayer:
# player 的焦点在脚底,所以需要偏移 player 的高度。注意 y 轴是向下的,所以是减去 player 的高度 # player 的焦点在脚底,所以需要偏移 player 的高度。注意 y 轴是向下的,所以是减去 player 的高度
target_position.y -= focusing_node.current_animation_config.os_height * 0.7 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
# )
# easing with speed # easing with speed
var new_position = lerp(global_position, target_position, speed * delta) var new_position = lerp(global_position, target_position, speed * delta)
# var new_position = global_position + (target_position - global_position) * speed * delta # var new_position = global_position + (target_position - global_position) * speed * delta
# clamp the position # clamp the position
var margin = half_screen_size / zoom_ratio var margin = half_screen_size / zoom_ratio
# var margin = half_screen_size
margin.y += shaded_height margin.y += shaded_height
new_position.x = clamp(new_position.x, limit_left + margin.x, limit_right - margin.x) 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) new_position.y = clamp(new_position.y, limit_top + margin.y, limit_bottom - margin.y)
global_position = new_position global_position = new_position
# var taget_zoom = lerpf(zoom.x, zoom_ratio, speed * delta)
# zoom = Vector2(taget_zoom, taget_zoom)
zoom = Vector2(zoom_ratio, zoom_ratio) zoom = Vector2(zoom_ratio, zoom_ratio)
@ -91,6 +88,7 @@ func tween_zoom(ratio: float, duration := 1.5):
. tween_property(self, "zoom_ratio", ratio, duration) . tween_property(self, "zoom_ratio", ratio, duration)
. set_trans(Tween.TRANS_SINE) . set_trans(Tween.TRANS_SINE)
. set_ease(Tween.EASE_IN_OUT) . set_ease(Tween.EASE_IN_OUT)
. from(zoom_ratio)
) )
# if refocus: # if refocus:
# zooming_and_focus_start_position = global_position # zooming_and_focus_start_position = global_position
@ -104,9 +102,27 @@ func tween_zoom(ratio: float, duration := 1.5):
# ) # )
func focus_node(node: Node2D) -> void: var tween_focus: Tween
func focus_node(node: Node2D, duration := 0.0) -> void:
if focusing_node == node:
return
if not node:
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)
)
focusing_node = node focusing_node = node
# zooming_and_focus_start_position = global_position
# var exited := false # var exited := false
# var exit_position: Vector2 # var exit_position: Vector2

View File

@ -1,4 +1,4 @@
[gd_scene load_steps=34 format=3 uid="uid://dlx5xxbg53rb8"] [gd_scene load_steps=33 format=3 uid="uid://dlx5xxbg53rb8"]
[ext_resource type="PackedScene" uid="uid://dayyx4jerj7io" path="res://scene/ground/ground.tscn" id="1_ff4yb"] [ext_resource type="PackedScene" uid="uid://dayyx4jerj7io" path="res://scene/ground/ground.tscn" id="1_ff4yb"]
[ext_resource type="Script" path="res://scene/ground/scene/c01/s05_animation.gd" id="2_j5oim"] [ext_resource type="Script" path="res://scene/ground/scene/c01/s05_animation.gd" id="2_j5oim"]
@ -10,7 +10,6 @@
[ext_resource type="Texture2D" uid="uid://eamkmbyicbkd" path="res://asset/art/scene/c01/s05_院长房间/e_座钟.png" id="7_3tetc"] [ext_resource type="Texture2D" uid="uid://eamkmbyicbkd" path="res://asset/art/scene/c01/s05_院长房间/e_座钟.png" id="7_3tetc"]
[ext_resource type="Texture2D" uid="uid://qtksfmfvk3c7" path="res://asset/art/scene/c01/s05_院长房间/e_床.png" id="7_xakd0"] [ext_resource type="Texture2D" uid="uid://qtksfmfvk3c7" path="res://asset/art/scene/c01/s05_院长房间/e_床.png" id="7_xakd0"]
[ext_resource type="Texture2D" uid="uid://dihrl7mgckinx" path="res://asset/art/scene/c01/s05_院长房间/e_钢琴.png" id="8_mnduo"] [ext_resource type="Texture2D" uid="uid://dihrl7mgckinx" path="res://asset/art/scene/c01/s05_院长房间/e_钢琴.png" id="8_mnduo"]
[ext_resource type="AudioStream" uid="uid://byjcmxy5crce5" path="res://asset/audio/sfx/ui/纸条.mp3" id="9_8debu"]
[ext_resource type="Texture2D" uid="uid://cmrpf3w0oetem" path="res://asset/art/scene/c01/s05_院长房间/e_桌椅.png" id="9_x837o"] [ext_resource type="Texture2D" uid="uid://cmrpf3w0oetem" path="res://asset/art/scene/c01/s05_院长房间/e_桌椅.png" id="9_x837o"]
[ext_resource type="PackedScene" uid="uid://jr1yd46wm5je" path="res://scene/entity/note.tscn" id="10_18v0g"] [ext_resource type="PackedScene" uid="uid://jr1yd46wm5je" path="res://scene/entity/note.tscn" id="10_18v0g"]
[ext_resource type="Texture2D" uid="uid://choqjery7hf58" path="res://asset/art/scene/c01/s05_院长房间/e_画框.png" id="11_6gq1s"] [ext_resource type="Texture2D" uid="uid://choqjery7hf58" path="res://asset/art/scene/c01/s05_院长房间/e_画框.png" id="11_6gq1s"]
@ -614,9 +613,6 @@ texture = ExtResource("9_x837o")
title_filter = "c01" title_filter = "c01"
note_key = "c01_院长书桌" note_key = "c01_院长书桌"
[node name="Sfx" parent="Ground/DeployLayer/桌椅" index="0"]
stream = ExtResource("9_8debu")
[node name="Sign" parent="Ground/DeployLayer/桌椅" index="1"] [node name="Sign" parent="Ground/DeployLayer/桌椅" index="1"]
offset_top = -21.0 offset_top = -21.0
offset_bottom = 59.0 offset_bottom = 59.0
@ -632,9 +628,6 @@ texture = ExtResource("11_6gq1s")
title_filter = "c01" title_filter = "c01"
note_key = "c01_倾斜的洋相片" note_key = "c01_倾斜的洋相片"
[node name="Sfx" parent="Ground/DeployLayer/画框" index="0"]
stream = ExtResource("9_8debu")
[node name="Sign" parent="Ground/DeployLayer/画框" index="1"] [node name="Sign" parent="Ground/DeployLayer/画框" index="1"]
offset_left = 3.0 offset_left = 3.0
offset_top = -7.0 offset_top = -7.0
@ -675,9 +668,6 @@ frame = 10
[node name="oneshot纸片" parent="Ground/DeployLayer" index="9" instance=ExtResource("14_lq1ou")] [node name="oneshot纸片" parent="Ground/DeployLayer" index="9" instance=ExtResource("14_lq1ou")]
position = Vector2(231, 77) position = Vector2(231, 77)
[node name="SfxInvalid" parent="Ground/DeployLayer/oneshot纸片" index="0"]
stream = ExtResource("16_j2w12")
[node name="SfxSuccess" parent="Ground/DeployLayer/oneshot纸片" index="1"] [node name="SfxSuccess" parent="Ground/DeployLayer/oneshot纸片" index="1"]
stream = ExtResource("17_yfgov") stream = ExtResource("17_yfgov")
file = "物品查看.mp3" file = "物品查看.mp3"

View File

@ -78,8 +78,9 @@ func _dean_flip_book() -> void:
func game_intro() -> void: func game_intro() -> void:
var camera = SceneManager.get_camera_marker() as CameraFocusMarker var camera = SceneManager.get_camera_marker() as CameraFocusMarker
camera.tween_zoom(1.5) camera.tween_zoom(1.5, 3.0)
camera.focus_node(focus_point) camera.focus_node(focus_point, 3.0)
# get_tree().create_timer(1.0).timeout.connect(camera.focus_node.bind(focus_point, 3.))
standing_kid1.play("【站立小孩-1】挠痒呼吸") standing_kid1.play("【站立小孩-1】挠痒呼吸")
standing_kid2.play("【站立小孩-2】转身") standing_kid2.play("【站立小孩-2】转身")
standing_kid3.play("【站立小孩-3】转身") standing_kid3.play("【站立小孩-3】转身")
@ -90,7 +91,7 @@ func game_intro() -> void:
func _game_counting_down(_res = null): func _game_counting_down(_res = null):
# 重置镜头 # 重置镜头
SceneManager.focus_player_and_reset_zoom() SceneManager.focus_player_and_reset_zoom(2.5)
DialogueManager.show_dialogue_balloon( DialogueManager.show_dialogue_balloon(
dialogue_c01, "c01_s06_猫鼠游戏", [GlobalConfig.DIALOG_IGNORE_INPUT] dialogue_c01, "c01_s06_猫鼠游戏", [GlobalConfig.DIALOG_IGNORE_INPUT]
) )

View File

@ -1,4 +1,4 @@
[gd_scene load_steps=25 format=3 uid="uid://bx16c8nn32f40"] [gd_scene load_steps=23 format=3 uid="uid://bx16c8nn32f40"]
[ext_resource type="PackedScene" uid="uid://dayyx4jerj7io" path="res://scene/ground/ground.tscn" id="1_bitx7"] [ext_resource type="PackedScene" uid="uid://dayyx4jerj7io" path="res://scene/ground/ground.tscn" id="1_bitx7"]
[ext_resource type="Script" path="res://scene/ground/scene/c01/s06_animation.gd" id="2_fkfhi"] [ext_resource type="Script" path="res://scene/ground/scene/c01/s06_animation.gd" id="2_fkfhi"]
@ -15,8 +15,6 @@
[ext_resource type="PackedScene" uid="uid://bnf3lkcbpx1ar" path="res://scene/entity/ambush.tscn" id="11_tudob"] [ext_resource type="PackedScene" uid="uid://bnf3lkcbpx1ar" path="res://scene/entity/ambush.tscn" id="11_tudob"]
[ext_resource type="PackedScene" uid="uid://jr1yd46wm5je" path="res://scene/entity/note.tscn" id="12_28t76"] [ext_resource type="PackedScene" uid="uid://jr1yd46wm5je" path="res://scene/entity/note.tscn" id="12_28t76"]
[ext_resource type="PackedScene" uid="uid://cw3q5pvciumil" path="res://scene/entity/interactable.tscn" id="12_idjp0"] [ext_resource type="PackedScene" uid="uid://cw3q5pvciumil" path="res://scene/entity/interactable.tscn" id="12_idjp0"]
[ext_resource type="AudioStream" uid="uid://inmdv5gqqius" path="res://asset/audio/sfx/ui/门锁互动.mp3" id="13_5s1q8"]
[ext_resource type="AudioStream" uid="uid://ccng5y2fip6mc" path="res://asset/audio/sfx/ui/开锁声.mp3" id="14_4tl6s"]
[sub_resource type="Animation" id="Animation_723yg"] [sub_resource type="Animation" id="Animation_723yg"]
length = 0.001 length = 0.001
@ -191,9 +189,7 @@ action_configs = Array[Dictionary]([{
[node name="游戏中途桌椅" parent="Ground/DeployLayer" index="9" instance=ExtResource("8_ouldg")] [node name="游戏中途桌椅" parent="Ground/DeployLayer" index="9" instance=ExtResource("8_ouldg")]
position = Vector2(2233, -1) position = Vector2(2233, -1)
sprite_frames = ExtResource("7_dsj2r") sprite_frames = ExtResource("7_dsj2r")
animation = &"桌椅翻倒" animation = &"桌椅正常"
frame = 5
frame_progress = 1.0
action_configs = Array[Dictionary]([{ action_configs = Array[Dictionary]([{
"animation_intro": &"桌椅颤抖-正常", "animation_intro": &"桌椅颤抖-正常",
"animation_next": "桌椅正常" "animation_next": "桌椅正常"
@ -205,12 +201,6 @@ action_configs = Array[Dictionary]([{
[node name="Interactable桌椅" parent="Ground/DeployLayer" index="10" instance=ExtResource("12_idjp0")] [node name="Interactable桌椅" parent="Ground/DeployLayer" index="10" instance=ExtResource("12_idjp0")]
position = Vector2(2135, 49) position = Vector2(2135, 49)
[node name="SfxInvalid" parent="Ground/DeployLayer/Interactable桌椅" index="0"]
stream = ExtResource("13_5s1q8")
[node name="SfxSuccess" parent="Ground/DeployLayer/Interactable桌椅" index="1"]
stream = ExtResource("14_4tl6s")
[node name="TextureContainer" parent="Ground/DeployLayer/Interactable桌椅/Sign" index="0"] [node name="TextureContainer" parent="Ground/DeployLayer/Interactable桌椅/Sign" index="0"]
metadata/_edit_use_anchors_ = true metadata/_edit_use_anchors_ = true
@ -333,7 +323,7 @@ z_index = 6
z_as_relative = false z_as_relative = false
position = Vector2(-23, 1) position = Vector2(-23, 1)
sprite_frames = ExtResource("7_dsj2r") sprite_frames = ExtResource("7_dsj2r")
animation = &"【墙上小孩猫影子】变身" animation = &"【单残疾小孩】爬行"
autostart = false autostart = false
move_configs = Array[Dictionary]([{ move_configs = Array[Dictionary]([{
"animation": &"【单残疾小孩】爬行", "animation": &"【单残疾小孩】爬行",
@ -419,11 +409,22 @@ animation = &"右绿衣男孩呼吸"
position = Vector2(333, 9.5) position = Vector2(333, 9.5)
sprite_frames = ExtResource("2_l4axy") sprite_frames = ExtResource("2_l4axy")
animation = &"红衣姑娘呼吸" animation = &"红衣姑娘呼吸"
action_configs = Array[Dictionary]([{
"animation_intro": &"红衣姑娘抬头",
"animation_next": "红衣姑娘呼吸"
}])
[node name="门口_院长" parent="Ground/ParallaxForeground/BGParallaxLayer" index="5" instance=ExtResource("8_ouldg")] [node name="门口_院长" parent="Ground/ParallaxForeground/BGParallaxLayer" index="5" instance=ExtResource("8_ouldg")]
position = Vector2(301, 8.5) position = Vector2(301, 8.5)
sprite_frames = ExtResource("2_l4axy") sprite_frames = ExtResource("2_l4axy")
animation = &"院长翻书" animation = &"院长呼吸"
action_configs = Array[Dictionary]([{
"animation_intro": "院长翻书",
"animation_next": "院长呼吸"
}, {
"animation_intro": &"院长抬头",
"animation_next": "院长呼吸"
}])
[node name="门口_左2黄衣男" parent="Ground/ParallaxForeground/BGParallaxLayer" index="6" instance=ExtResource("8_ouldg")] [node name="门口_左2黄衣男" parent="Ground/ParallaxForeground/BGParallaxLayer" index="6" instance=ExtResource("8_ouldg")]
position = Vector2(273, 15) position = Vector2(273, 15)

View File

@ -112,7 +112,7 @@ func _on_finished():
marker.global_position = main_character.global_position marker.global_position = main_character.global_position
var target_y = marker.global_position.y - building_y var target_y = marker.global_position.y - building_y
var camera = SceneManager.get_camera_marker() var camera = SceneManager.get_camera_marker()
camera.focus_node(marker) camera.focus_node(marker, 2.0)
camera.shake_enabled = true camera.shake_enabled = true
camera.shake_strength = 0.5 camera.shake_strength = 0.5
camera.shake_recovery_speed = 4.0 camera.shake_recovery_speed = 4.0

View File

@ -22,7 +22,6 @@ current_scene = "c01_s05"
entrance_portal = "right" entrance_portal = "right"
[node name="ShadingLayer" parent="." instance=ExtResource("2_d1re1")] [node name="ShadingLayer" parent="." instance=ExtResource("2_d1re1")]
fog_frame = 15
[node name="PropInspector" parent="." instance=ExtResource("5_ux0rw")] [node name="PropInspector" parent="." instance=ExtResource("5_ux0rw")]
unique_name_in_owner = true unique_name_in_owner = true

View File

@ -18,7 +18,6 @@ var mode: Array[String] = ["vignette"] as Array[String]:
if is_node_ready(): if is_node_ready():
%Vignette.material.set("shader_parameter/vignette_intensity", new_val) %Vignette.material.set("shader_parameter/vignette_intensity", new_val)
@export_group("Fog", "fog_") @export_group("Fog", "fog_")
const fog_frame_count = 24 # 0-23
@export var fog_offset := FOG_OFFSET_DEFAULT: @export var fog_offset := FOG_OFFSET_DEFAULT:
set(new_val): set(new_val):
fog_offset = new_val fog_offset = new_val

View File

@ -235,7 +235,6 @@ shader_parameter/vignette_rgb = Color(0.247059, 0.14902, 0.192157, 1)
layer = 10 layer = 10
script = ExtResource("1_6w7er") script = ExtResource("1_6w7er")
mode = Array[String]([]) mode = Array[String]([])
fog_frame = 15
[node name="Sprite2D" type="Sprite2D" parent="."] [node name="Sprite2D" type="Sprite2D" parent="."]
unique_name_in_owner = true unique_name_in_owner = true
@ -293,7 +292,7 @@ material = SubResource("ShaderMaterial_fv2fx")
position = Vector2(286, 161) position = Vector2(286, 161)
sprite_frames = SubResource("SpriteFrames_xeqgs") sprite_frames = SubResource("SpriteFrames_xeqgs")
animation = &"inverted_point_light_masks" animation = &"inverted_point_light_masks"
frame = 15 frame = 23
offset = Vector2(0, 50) offset = Vector2(0, 50)
[node name="BackBufferCopy" type="BackBufferCopy" parent="Fog"] [node name="BackBufferCopy" type="BackBufferCopy" parent="Fog"]