优化 camera 与 marker 的交互表现

This commit is contained in:
cakipaul 2025-01-21 21:49:37 +08:00
parent 675ae26d6a
commit fcbe276da9
15 changed files with 224 additions and 173 deletions

View File

@ -23,7 +23,7 @@ func get_ground() -> Ground2D:
return null return null
func get_camera_marker(): func get_camera_marker() -> CameraFocusMarker:
var ground = get_ground() var ground = get_ground()
if ground: if ground:
return ground.camera_focus_marker return ground.camera_focus_marker
@ -37,33 +37,17 @@ func get_player() -> MainPlayer:
return null return null
func focus_nodepath(node_path: NodePath) -> void: func focus_node(node: Node2D) -> void:
if not node_path:
printerr("Node path is empty")
return
var node = get_node_or_null(node_path)
if node:
focus_node(node)
else:
printerr("Node not found:", node_path)
func focus_node(node: CanvasItem) -> void:
var ground = get_ground()
if ground:
ground.focus_node(node)
func focus_player() -> void:
var ground = get_ground()
if ground:
ground.focus_player()
func focus_player_and_reset_zoom(duration := 1) -> void:
var marker = get_camera_marker() var marker = get_camera_marker()
if marker: if marker:
marker.tween_zoom(1.0, duration).tween_callback(focus_player) marker.focus_node(node)
func focus_player_and_reset_zoom(duration := 1.2) -> void:
var marker = get_camera_marker()
if marker:
marker.tween_zoom(1.0, duration, true)
marker.focus_node(get_player())
# action_locked 用于设置界面等强制锁定action_freezed 用于查看物品等锁定 # action_locked 用于设置界面等强制锁定action_freezed 用于查看物品等锁定

View File

@ -8,7 +8,7 @@ signal quit_inspecting
# set(value): # set(value):
# entity_config = value # entity_config = value
enum { STATUS_NORAML, STATUS_INSPECTING_COVER, STATUS_INSPECTING_NOTES } enum { STATUS_NORAML, STATUS_TRANSITIONING, STATUS_INSPECTING_COVER, STATUS_INSPECTING_NOTES }
@export var entity_name: String = "" @export var entity_name: String = ""
@export var texture_cover: Texture2D @export var texture_cover: Texture2D
@ -23,7 +23,7 @@ var content_key: String = ""
@onready var area2d = %Area2D as Area2D @onready var area2d = %Area2D as Area2D
@onready var sfx = %Sfx @onready var sfx = %Sfx
@onready var container = %Container @onready var container = %Container
@onready var cover_rect = %Cover as TextureRect @onready var cover_rect = %Cover as TextureRect
@onready var content_label = %ContentLabel as Label @onready var content_label = %ContentLabel as Label
@onready var tip_label = %TipLabel as Label @onready var tip_label = %TipLabel as Label
@ -37,7 +37,7 @@ static var content_dialogue = (
var status := STATUS_NORAML var status := STATUS_NORAML
var blinking_tween: Tween var blinking_tween: Tween
var inspected_time = 0.0
func _ready() -> void: func _ready() -> void:
$InspectLayer.layer = GlobalConfig.CANVAS_LAYER_PROP_INSPECTOR $InspectLayer.layer = GlobalConfig.CANVAS_LAYER_PROP_INSPECTOR
@ -50,6 +50,7 @@ func _ready() -> void:
sign_mark.interacted.connect(_on_interacted) sign_mark.interacted.connect(_on_interacted)
sign_mark.cancel.connect(_on_cancel) sign_mark.cancel.connect(_on_cancel)
func _get_tr_content(): func _get_tr_content():
if content_key == "": if content_key == "":
return "" return ""
@ -65,15 +66,16 @@ func _get_tr_content():
func _on_interacted() -> void: func _on_interacted() -> void:
# 1s 内锁定交互,留给镜头复位时间 if STATUS_TRANSITIONING == status:
if Time.get_ticks_msec() - inspected_time < 1500:
return return
if status == STATUS_NORAML: if status == STATUS_NORAML:
sfx.play() sfx.play()
inspected_time = Time.get_ticks_msec()
SceneManager.focus_node(self) SceneManager.focus_node(self)
SceneManager.get_camera_marker().tween_zoom(2.0) SceneManager.get_camera_marker().tween_zoom(2.0)
status = STATUS_INSPECTING_COVER status = STATUS_TRANSITIONING
var tween = create_tween()
tween.tween_interval(0.7)
tween.tween_callback(func(): status = STATUS_INSPECTING_COVER)
sign_mark.display_sign = false sign_mark.display_sign = false
SceneManager.freeze_player(0.0, PlayerAnimationConfig.ACTION_LOOKUP_WALL) SceneManager.freeze_player(0.0, PlayerAnimationConfig.ACTION_LOOKUP_WALL)
cover_rect.texture = texture_cover cover_rect.texture = texture_cover
@ -105,15 +107,18 @@ func _blink_label(init := true):
func _on_cancel(_body = null): func _on_cancel(_body = null):
# inspected_time = Time.get_ticks_msec() if STATUS_TRANSITIONING == status:
return
if status != STATUS_NORAML: if status != STATUS_NORAML:
quit_inspecting.emit() quit_inspecting.emit()
status = STATUS_NORAML status = STATUS_TRANSITIONING
var tween = create_tween() var tween = create_tween()
tween.tween_property(container, "modulate:a", 0.0, 0.15) tween.tween_property(container, "modulate:a", 0.0, 0.15)
if blinking_tween and blinking_tween.is_running(): if blinking_tween and blinking_tween.is_running():
blinking_tween.kill() blinking_tween.kill()
tween.parallel().tween_property(tip_label, "modulate:a", 0.0, 0.15) tween.parallel().tween_property(tip_label, "modulate:a", 0.0, 0.15)
tween.tween_interval(1.0)
tween.tween_callback(func(): status = STATUS_NORAML)
SceneManager.focus_player_and_reset_zoom() SceneManager.focus_player_and_reset_zoom()
SceneManager.release_player() SceneManager.release_player()
sign_mark.display_sign = true sign_mark.display_sign = true

View File

@ -1,11 +1,10 @@
# @tool @tool
class_name Portal2D extends Sprite2D class_name Portal2D extends Sprite2D
@export var enabled := true: @export var enabled := true:
set(val): set(val):
enabled = val enabled = val
if is_node_ready(): _check_sign_mark()
_check_sign_mark()
@export var immediately := true @export var immediately := true
@export_enum("left", "right", "1", "2", "3", "4", "5", "6", "7", "8", "9") var portal_name := "left": @export_enum("left", "right", "1", "2", "3", "4", "5", "6", "7", "8", "9") var portal_name := "left":
set(value): set(value):
@ -19,15 +18,13 @@ class_name Portal2D extends Sprite2D
var target_portal := "none": var target_portal := "none":
set(value): set(value):
target_portal = value target_portal = value
if is_node_ready(): _check_sign_mark()
_check_sign_mark()
@export var default_texture: Texture2D @export var default_texture: Texture2D
@export var opened_texture: Texture2D @export var opened_texture: Texture2D
@export var opened := false: @export var opened := false:
set(new_val): set(new_val):
opened = new_val opened = new_val
if is_node_ready(): _checkout_texture()
_checkout_texture()
@onready var sfx = %Sfx as Sfx @onready var sfx = %Sfx as Sfx
@onready var sign_mark = %Sign as Sign @onready var sign_mark = %Sign as Sign
@ -61,6 +58,8 @@ func _checkout_texture():
texture = default_texture texture = default_texture
func _check_sign_mark(): func _check_sign_mark():
if not is_node_ready():
return
if target_portal == "none" or not enabled: if target_portal == "none" or not enabled:
sign_mark.enabled = false sign_mark.enabled = false
else: else:

View File

@ -1,6 +1,7 @@
class_name CameraFocusMarker extends Marker2D class_name CameraFocusMarker extends Camera2D
@export var camera: Camera2D @export var focusing_node: Node2D
@export var force_offset := Vector2.ZERO
@export_group("Status") @export_group("Status")
@export var lock_horizontal = true @export var lock_horizontal = true
@export_group("Config") @export_group("Config")
@ -11,89 +12,110 @@ class_name CameraFocusMarker extends Marker2D
@export var shake_enabled := false @export var shake_enabled := false
@export var shake_strength := 2.0 @export var shake_strength := 2.0
@export var shake_recovery_speed := 8.0 @export var shake_recovery_speed := 8.0
@export_group("Limit", "limit_") # @export_group("Limit", "limit_")
@export var limit_left := 0.0 # @export var limit_left := 0.0
@export var limit_right := 564.0 # @export var limit_right := 564.0
# @export var limit_top := -158.0 # @export var limit_top := 0
# @export var limit_bottom := 158.0 # @export var limit_bottom := 316.0
@export var limit_top := 0
@export var limit_bottom := 316.0
@export var zoom_ratio := 1.0 @export var zoom_ratio := 1.0
@onready var target = %Target as Node2D var _tweeked_position := Vector2.ZERO
var zoom_tween: Tween var zoom_tween: Tween
var zooming_and_focus_start_position: Vector2
# 0 to 1
var zooming_and_focus_progress := 1.0
func _ready() -> void: func _ready() -> void:
if not camera: if not focusing_node:
push_error("Camera2D node not found") push_error("Focusing node not found")
func reset_position_immediately():
if focusing_node:
global_position = focusing_node.global_position + _tweeked_position + force_offset
func tweak_position(velocity, facing_direction): func tweak_position(velocity, facing_direction):
var ideal_x = facing_direction.x * min(50.0, 0.5 * abs(velocity.x)) var ideal_x = facing_direction.x * min(50.0, 0.5 * abs(velocity.x))
var current_x = target.position.x var current_x = _tweeked_position.x
var delta = ideal_x - current_x var delta = ideal_x - current_x
if abs(delta) > 10.0: if abs(delta) > 10.0:
target.position.x = move_toward(current_x, ideal_x, speed * 2.0) _tweeked_position.x = move_toward(current_x, ideal_x, speed * 2.0)
if lock_horizontal: if lock_horizontal:
global_position.y = 0 global_position.y = 0
target.position.y = 0 _tweeked_position.y = 0
else: else:
target.position.y = facing_direction.y * abs(velocity.y) * 0.2 _tweeked_position.y = facing_direction.y * abs(velocity.y) * 0.2
func _physics_process(delta: float) -> void: func _physics_process(delta: float) -> void:
if not camera:
return
# set camera's position # set camera's position
var target_position = target.global_position var target_position = focusing_node.global_position + _tweeked_position + force_offset
var current_position = camera.global_position 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
)
# easing with speed # easing with speed
var position_delta = (target_position - current_position) * speed * delta var new_position = global_position + (target_position - global_position) * speed * delta
var new_position = current_position + position_delta
# clamp the position # clamp the position
var margin = half_screen_size / zoom_ratio var margin = half_screen_size / zoom_ratio
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)
camera.global_position = new_position global_position = new_position
camera.zoom = Vector2(zoom_ratio, zoom_ratio) zoom = Vector2(zoom_ratio, zoom_ratio)
func tween_zoom(ratio: float, duration := .7) -> Tween: func tween_zoom(ratio: float, duration := 1.5, refocus := false):
if zoom_tween and zoom_tween.is_running(): if zoom_tween and zoom_tween.is_running():
zoom_tween.kill() zoom_tween.kill()
zoom_tween = create_tween() zoom_tween = create_tween()
if duration <= 0.0: (
zoom_ratio = ratio zoom_tween
else: . 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
( (
zoom_tween zoom_tween
. tween_property(self, "zoom_ratio", ratio, duration) . parallel()
. set_trans(Tween.TRANS_CUBIC) . tween_property(self, "zooming_and_focus_progress", 1.0, duration)
. from(0.0)
. set_trans(Tween.TRANS_LINEAR)
. set_ease(Tween.EASE_IN_OUT) . set_ease(Tween.EASE_IN_OUT)
) )
return zoom_tween
var exited := false func focus_node(node: Node2D) -> void:
var exit_position: Vector2 focusing_node = node
var enter_tree_tween: Tween
# var exited := false
# var exit_position: Vector2
# var enter_tree_tween: Tween
func _exit_tree() -> void: # func _exit_tree() -> void:
exit_position = global_position # exit_position = global_position
exited = true # exited = true
# func _enter_tree() -> void:
func _enter_tree() -> void: # if exited and is_node_ready():
if exited: # exited = false
if enter_tree_tween and enter_tree_tween.is_running(): # if enter_tree_tween and enter_tree_tween.is_running():
enter_tree_tween.kill() # enter_tree_tween.kill()
exited = false # enter_tree_tween = create_tween()
global_position = exit_position # global_position = exit_position
enter_tree_tween = create_tween() # enter_tree_tween.tween_property(self, "position", Vector2.ZERO, 0.2).set_trans(
enter_tree_tween.tween_property(self, "position", Vector2.ZERO, 0.2).set_trans( # Tween.TRANS_CUBIC
Tween.TRANS_CUBIC # )
)

View File

@ -2,8 +2,5 @@
[ext_resource type="Script" path="res://scene/ground/camera/camera_focus_marker.gd" id="1_7t4e6"] [ext_resource type="Script" path="res://scene/ground/camera/camera_focus_marker.gd" id="1_7t4e6"]
[node name="CameraFocusMarker" type="Marker2D"] [node name="CameraFocusMarker" type="Camera2D"]
script = ExtResource("1_7t4e6") script = ExtResource("1_7t4e6")
[node name="Target" type="Node2D" parent="."]
unique_name_in_owner = true

View File

@ -15,8 +15,8 @@ var default_portal := "left"
@export var reset_player_pos := false: @export var reset_player_pos := false:
set(val): set(val):
reset_player_pos = false reset_player_pos = false
_reset_player_positon() if is_node_ready():
@export var camera_focus_marker: CameraFocusMarker _reset_player_positon()
@export_group("Sound") @export_group("Sound")
@export_enum("none", "ghost", "walking", "running", "crawling", "concrete") @export_enum("none", "ghost", "walking", "running", "crawling", "concrete")
var footstep_type: String = "concrete": var footstep_type: String = "concrete":
@ -29,7 +29,7 @@ var footstep_type: String = "concrete":
@onready var directional_light := %DirectionalLight2D as DirectionalLight2D @onready var directional_light := %DirectionalLight2D as DirectionalLight2D
@onready var bg_sprite = %BGSprite2D as Sprite2D @onready var bg_sprite = %BGSprite2D as Sprite2D
@onready var foreground = %ParallaxForeground as ParallaxBackground @onready var foreground = %ParallaxForeground as ParallaxBackground
@onready var camera = %Camera2D as Camera2D @onready var camera_focus_marker = %CameraFocusMarker as CameraFocusMarker
@onready var footstep_audio = %FootstepAudioPlayer as RandomAudioStreamPlayer @onready var footstep_audio = %FootstepAudioPlayer as RandomAudioStreamPlayer
@ -53,16 +53,15 @@ func _ready() -> void:
return return
# 检查 scene_name 是否合法 # 检查 scene_name 是否合法
scene_name = scene_name.strip_edges() scene_name = scene_name.strip_edges()
if not scene_name or scene_name.length() != 7: if get_parent().name.begins_with("S") and (not scene_name or scene_name.length() != 7):
printerr("scene_name is not valid") printerr("scene_name is not valid")
return
_reset_player_positon()
if Engine.is_editor_hint(): if Engine.is_editor_hint():
return return
foreground.layer = GlobalConfig.CANVAS_LAYER_FG foreground.layer = GlobalConfig.CANVAS_LAYER_FG
_set_camera_and_player_boundary() _set_camera_and_player_boundary()
_load_footstep_audio() _load_footstep_audio()
focus_player() # marker 默认就在 foucs player 状态
# camera_focus_marker.focus_node(player)
# %ColorRectTop.visible = true # %ColorRectTop.visible = true
# %ColorRectBottom.visible = true # %ColorRectBottom.visible = true
# 如果 debug 模式下不通过 GroundLoader 启动,则插入到 main 以下 # 如果 debug 模式下不通过 GroundLoader 启动,则插入到 main 以下
@ -83,12 +82,12 @@ func _restart_from_main():
func _enter_tree() -> void: func _enter_tree() -> void:
if camera: if camera_focus_marker:
camera.enabled = true camera_focus_marker.enabled = true
func _reset_player_positon(): func _reset_player_positon():
player.position.x = $DeployLayer/portal_left.position.x move_player_to_portal(default_portal)
# 从屏幕下边缘算起 # 从屏幕下边缘算起
player.set_y_from_ground(158.0 - player_y) player.set_y_from_ground(158.0 - player_y)
@ -125,29 +124,7 @@ func play_footstep_sound() -> void:
footstep_audio.play_random() footstep_audio.play_random()
var focus_mutex := Mutex.new() func move_player_to_portal(portal_name: String) -> void:
func get_player() -> MainPlayer:
return player
func focus_node(node: CanvasItem) -> void:
if node.is_ancestor_of(camera_focus_marker):
return
focus_mutex.lock()
var parent = camera_focus_marker.get_parent()
if parent:
parent.remove_child(camera_focus_marker)
node.add_child(camera_focus_marker)
focus_mutex.unlock()
func focus_player() -> void:
focus_node(player)
func move_player_to_portal(portal_name := default_portal) -> void:
var portal_node = get_node_or_null("DeployLayer/portal_" + portal_name) as Node2D var portal_node = get_node_or_null("DeployLayer/portal_" + portal_name) as Node2D
if portal_node: if portal_node:
player.global_position.x = portal_node.global_position.x player.global_position.x = portal_node.global_position.x
@ -155,3 +132,5 @@ func move_player_to_portal(portal_name := default_portal) -> void:
print("move player to portal:", portal_name, portal_node.global_position) print("move player to portal:", portal_name, portal_node.global_position)
else: else:
printerr(scene_name + " portal not found: " + portal_name) printerr(scene_name + " portal not found: " + portal_name)
# 传送后,重置 camera 位置
camera_focus_marker.reset_position_immediately()

View File

@ -14,9 +14,8 @@ func _ready() -> void:
layer = GlobalConfig.CANVAS_LAYER_HD_ENTITY layer = GlobalConfig.CANVAS_LAYER_HD_ENTITY
" "
[node name="Ground" type="Node2D" node_paths=PackedStringArray("camera_focus_marker")] [node name="Ground" type="Node2D"]
script = ExtResource("1_0vrlo") script = ExtResource("1_0vrlo")
camera_focus_marker = NodePath("MainPlayer/CameraFocusMarker")
[node name="AnimationPlayer" type="AnimationPlayer" parent="."] [node name="AnimationPlayer" type="AnimationPlayer" parent="."]
@ -53,11 +52,21 @@ portal_name = "right"
[node name="MainPlayer" parent="." node_paths=PackedStringArray("camera_marker") instance=ExtResource("3_atha7")] [node name="MainPlayer" parent="." node_paths=PackedStringArray("camera_marker") instance=ExtResource("3_atha7")]
unique_name_in_owner = true unique_name_in_owner = true
position = Vector2(26, 88) position = Vector2(26, 88)
camera_marker = NodePath("CameraFocusMarker") camera_marker = NodePath("../CameraFocusMarker")
[node name="CameraFocusMarker" parent="MainPlayer" node_paths=PackedStringArray("camera") instance=ExtResource("4_mgk0a")] [node name="CameraFocusMarker" parent="." node_paths=PackedStringArray("focusing_node") instance=ExtResource("4_mgk0a")]
unique_name_in_owner = true unique_name_in_owner = true
camera = NodePath("../../Camera2D") position = Vector2(26, 88)
focusing_node = NodePath("../MainPlayer")
force_offset = null
lock_horizontal = null
speed = null
half_screen_size = null
shaded_height = null
shake_enabled = null
shake_strength = null
shake_recovery_speed = null
zoom_ratio = null
[node name="ParallaxForeground" type="ParallaxBackground" parent="."] [node name="ParallaxForeground" type="ParallaxBackground" parent="."]
unique_name_in_owner = true unique_name_in_owner = true
@ -101,6 +110,3 @@ height = 0.5
[node name="FootstepAudioPlayer" type="AudioStreamPlayer" parent="."] [node name="FootstepAudioPlayer" type="AudioStreamPlayer" parent="."]
unique_name_in_owner = true unique_name_in_owner = true
script = ExtResource("5_7mb2q") script = ExtResource("5_7mb2q")
[node name="Camera2D" type="Camera2D" parent="."]
unique_name_in_owner = true

View File

@ -69,15 +69,15 @@ func _load_save():
entrance_portal = ArchiveManager.archive.entrance_portal entrance_portal = ArchiveManager.archive.entrance_portal
func _toggle_mask(display: bool, _immediately: bool) -> Tween: func _toggle_mask(display: bool) -> Tween:
var tween = create_tween() var tween = get_tree().create_tween()
if display: if display:
tween.tween_property(mask, "color:a", 1.0, 0.3).set_trans(Tween.TRANS_CUBIC) tween.tween_property(mask, "color:a", 1.0, 0.3).set_trans(Tween.TRANS_CUBIC)
display_mask_time = Time.get_ticks_msec() display_mask_time = Time.get_ticks_msec()
else: else:
# var time = Time.get_ticks_msec() # var time = Time.get_ticks_msec()
# # 转场至少 0.6s, 除去 0.3s 最后的淡出,需要 0.3s 的等待时间(包含 mask 的淡入) # # 转场至少 0.6s, 除去 0.3s 最后的淡出,需要 0.3s 的等待时间(包含 mask 的淡入)
# if not _immediately: # if not immediately:
# var wait_time = max(display_mask_time + 300 - time, 0.0) * 0.001 # var wait_time = max(display_mask_time + 300 - time, 0.0) * 0.001
# if wait_time: # if wait_time:
# tween.tween_interval(wait_time) # tween.tween_interval(wait_time)
@ -93,10 +93,13 @@ func transition_to_scene(scene_name: String, portal: String, immediately: bool)
# 优先更新 archive使 ground 可以访问自己的 current_scene 键值 # 优先更新 archive使 ground 可以访问自己的 current_scene 键值
if not Engine.is_editor_hint(): if not Engine.is_editor_hint():
_update_archive() _update_archive()
# 转场效果,在 _load_ground_node 之前播放 if not immediately:
var tween = _toggle_mask(true, immediately) # 转场效果,在 _load_ground_node 之前播放
tween.tween_callback(_do_transition.bind(scene_name)) var tween = _toggle_mask(true)
tween.tween_callback(_toggle_mask.bind(false, immediately)) tween.tween_callback(_do_transition.bind(scene_name))
tween.tween_callback(_toggle_mask.bind(false))
else:
_do_transition(scene_name)
else: else:
print("Scene not found: " + scene_name) print("Scene not found: " + scene_name)
@ -127,12 +130,12 @@ func _do_transition(scene_name: String):
func _add_ground(): func _add_ground():
ground.name = "Ground" ground.name = "Ground"
add_child(ground) add_child(ground)
# 更新玩家位置 if not Engine.is_editor_hint():
if first_entered and not Engine.is_editor_hint():
_update_player_position_from_archive()
elif not Engine.is_editor_hint():
# move player to portal # move player to portal
ground.move_player_to_portal(entrance_portal) ground.move_player_to_portal(entrance_portal)
# 更新玩家位置
if first_entered:
_update_player_position_from_archive()
first_entered = false first_entered = false
# SceneManager.release_player() # SceneManager.release_player()

View File

@ -186,50 +186,50 @@ tracks/12/keys = {
tracks/13/type = "value" tracks/13/type = "value"
tracks/13/imported = false tracks/13/imported = false
tracks/13/enabled = true tracks/13/enabled = true
tracks/13/path = NodePath("MainPlayer/CameraFocusMarker:position") tracks/13/path = NodePath("DeployLayer/oneshot纸片/Sign:display_sign")
tracks/13/interp = 1 tracks/13/interp = 1
tracks/13/loop_wrap = true tracks/13/loop_wrap = true
tracks/13/keys = { tracks/13/keys = {
"times": PackedFloat32Array(0), "times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1), "transitions": PackedFloat32Array(1),
"update": 0, "update": 1,
"values": [Vector2(0, 0)] "values": [true]
} }
tracks/14/type = "value" tracks/14/type = "value"
tracks/14/imported = false tracks/14/imported = false
tracks/14/enabled = true tracks/14/enabled = true
tracks/14/path = NodePath("DeployLayer/oneshot纸片/Sign:display_sign") tracks/14/path = NodePath("DeployLayer/oneshot纸片/Sign:position")
tracks/14/interp = 1 tracks/14/interp = 1
tracks/14/loop_wrap = true tracks/14/loop_wrap = true
tracks/14/keys = { tracks/14/keys = {
"times": PackedFloat32Array(0), "times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1), "transitions": PackedFloat32Array(1),
"update": 1, "update": 0,
"values": [true] "values": [Vector2(3, -4)]
} }
tracks/15/type = "value" tracks/15/type = "value"
tracks/15/imported = false tracks/15/imported = false
tracks/15/enabled = true tracks/15/enabled = true
tracks/15/path = NodePath("DeployLayer/oneshot纸片/Sign:position") tracks/15/path = NodePath("CameraFocusMarker:zoom_ratio")
tracks/15/interp = 1 tracks/15/interp = 1
tracks/15/loop_wrap = true tracks/15/loop_wrap = true
tracks/15/keys = { tracks/15/keys = {
"times": PackedFloat32Array(0), "times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1), "transitions": PackedFloat32Array(1),
"update": 0, "update": 0,
"values": [Vector2(3, -4)] "values": [1.0]
} }
tracks/16/type = "value" tracks/16/type = "value"
tracks/16/imported = false tracks/16/imported = false
tracks/16/enabled = true tracks/16/enabled = true
tracks/16/path = NodePath("MainPlayer/CameraFocusMarker:zoom_ratio") tracks/16/path = NodePath("CameraFocusMarker:force_offset")
tracks/16/interp = 1 tracks/16/interp = 1
tracks/16/loop_wrap = true tracks/16/loop_wrap = true
tracks/16/keys = { tracks/16/keys = {
"times": PackedFloat32Array(0), "times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1), "transitions": PackedFloat32Array(1),
"update": 0, "update": 0,
"values": [1.0] "values": [Vector2(0, 0)]
} }
[sub_resource type="Animation" id="Animation_7k2c8"] [sub_resource type="Animation" id="Animation_7k2c8"]
@ -459,26 +459,26 @@ tracks/7/keys = {
tracks/8/type = "value" tracks/8/type = "value"
tracks/8/imported = false tracks/8/imported = false
tracks/8/enabled = true tracks/8/enabled = true
tracks/8/path = NodePath("MainPlayer/CameraFocusMarker:position") tracks/8/path = NodePath("CameraFocusMarker:zoom_ratio")
tracks/8/interp = 1 tracks/8/interp = 1
tracks/8/loop_wrap = true tracks/8/loop_wrap = true
tracks/8/keys = { tracks/8/keys = {
"times": PackedFloat32Array(0, 0.5, 3.98, 4.38), "times": PackedFloat32Array(0, 0.56, 3.52, 4.1),
"transitions": PackedFloat32Array(1, 1, 1, 1), "transitions": PackedFloat32Array(1, 1, 1, 1),
"update": 0, "update": 0,
"values": [Vector2(0, 0), Vector2(0, 10), Vector2(0, 10), Vector2(0, 0)] "values": [1.0, 1.5, 1.5, 1.0]
} }
tracks/9/type = "value" tracks/9/type = "value"
tracks/9/imported = false tracks/9/imported = false
tracks/9/enabled = true tracks/9/enabled = true
tracks/9/path = NodePath("MainPlayer/CameraFocusMarker:zoom_ratio") tracks/9/path = NodePath("CameraFocusMarker:force_offset")
tracks/9/interp = 1 tracks/9/interp = 1
tracks/9/loop_wrap = true tracks/9/loop_wrap = true
tracks/9/keys = { tracks/9/keys = {
"times": PackedFloat32Array(0.02, 0.54, 3.96, 4.38), "times": PackedFloat32Array(0, 0.5, 1.46, 2.28, 3.58, 4.08),
"transitions": PackedFloat32Array(1, 1, 1, 1), "transitions": PackedFloat32Array(1, 1, 1, 1, 1, 1),
"update": 0, "update": 0,
"values": [1.0, 1.5, 1.5, 1.0] "values": [Vector2(0, 0), Vector2(0, -50), Vector2(0, -50), Vector2(0, -90), Vector2(0, -90), Vector2(0, 0)]
} }
[sub_resource type="Animation" id="Animation_ocf0o"] [sub_resource type="Animation" id="Animation_ocf0o"]
@ -722,18 +722,27 @@ height = 50.0
[node name="MainPlayer" parent="Ground" index="5"] [node name="MainPlayer" parent="Ground" index="5"]
character = "小小蝶" character = "小小蝶"
[node name="CameraFocusMarker" parent="Ground" index="6"]
lock_horizontal = null
speed = null
half_screen_size = null
shaded_height = null
shake_enabled = null
shake_strength = null
shake_recovery_speed = null
[node name="FGSprite2D" parent="Ground/ParallaxForeground/FGParallaxLayer" index="0"] [node name="FGSprite2D" parent="Ground/ParallaxForeground/FGParallaxLayer" index="0"]
position = Vector2(21, 39) position = Vector2(21, 39)
texture = ExtResource("3_vmr0f") texture = ExtResource("3_vmr0f")
[node name="SubViewportContainer" parent="Ground" index="7"] [node name="SubViewportContainer" parent="Ground" index="8"]
offset_top = -2.0 offset_top = -2.0
offset_bottom = 1266.0 offset_bottom = 1266.0
[node name="HdLayer" parent="Ground/SubViewportContainer/SubViewport" index="0"] [node name="HdLayer" parent="Ground/SubViewportContainer/SubViewport" index="0"]
layer = -1 layer = -1
[node name="DirectionalLight2D" parent="Ground" index="8"] [node name="DirectionalLight2D" parent="Ground" index="9"]
visible = false visible = false
rotation = -0.000622023 rotation = -0.000622023
energy = 0.3 energy = 0.3

View File

@ -67,6 +67,17 @@ offset = Vector2(601.5, -0.5)
position = Vector2(144, 88) position = Vector2(144, 88)
character = "小小蝶" character = "小小蝶"
[node name="CameraFocusMarker" parent="Ground" index="6"]
force_offset = null
lock_horizontal = null
speed = null
half_screen_size = null
shaded_height = null
shake_enabled = null
shake_strength = null
shake_recovery_speed = null
zoom_ratio = null
[node name="柱子" type="Sprite2D" parent="Ground/ParallaxForeground/BGParallaxLayer" index="0"] [node name="柱子" type="Sprite2D" parent="Ground/ParallaxForeground/BGParallaxLayer" index="0"]
position = Vector2(0, 31) position = Vector2(0, 31)
texture = ExtResource("4_dtycx") texture = ExtResource("4_dtycx")
@ -118,7 +129,7 @@ sprite_frames = ExtResource("2_l4axy")
animation = &"fg_花圃" animation = &"fg_花圃"
offset = Vector2(1615, 0) offset = Vector2(1615, 0)
[node name="DirectionalLight2D" parent="Ground" index="8"] [node name="DirectionalLight2D" parent="Ground" index="9"]
energy = 0.3 energy = 0.3
blend_mode = 1 blend_mode = 1

View File

@ -41,6 +41,17 @@ position = Vector2(135, 56)
[node name="MainPlayer" parent="Ground" index="5"] [node name="MainPlayer" parent="Ground" index="5"]
position = Vector2(78, 88) position = Vector2(78, 88)
[node name="CameraFocusMarker" parent="Ground" index="6"]
force_offset = null
lock_horizontal = null
speed = null
half_screen_size = null
shaded_height = null
shake_enabled = null
shake_strength = null
shake_recovery_speed = null
zoom_ratio = null
[node name="FGSprite2D" parent="Ground/ParallaxForeground/FGParallaxLayer" index="0"] [node name="FGSprite2D" parent="Ground/ParallaxForeground/FGParallaxLayer" index="0"]
texture = null texture = null

View File

@ -44,6 +44,7 @@ size = Vector2(35, 70)
[node name="Ground" parent="." instance=ExtResource("1_wrr6r")] [node name="Ground" parent="." instance=ExtResource("1_wrr6r")]
scene_name = "c02_s02" scene_name = "c02_s02"
player_y = 60
[node name="AnimationPlayer" parent="Ground" index="0"] [node name="AnimationPlayer" parent="Ground" index="0"]
libraries = { libraries = {
@ -92,6 +93,20 @@ offset_bottom = 36.0
[node name="CollisionShape2D" parent="Ground/DeployLayer/纸人/Area2D" index="0"] [node name="CollisionShape2D" parent="Ground/DeployLayer/纸人/Area2D" index="0"]
shape = SubResource("RectangleShape2D_vc6i4") shape = SubResource("RectangleShape2D_vc6i4")
[node name="MainPlayer" parent="Ground" index="5"]
position = Vector2(26, 98)
[node name="CameraFocusMarker" parent="Ground" index="6"]
force_offset = null
lock_horizontal = null
speed = null
half_screen_size = null
shaded_height = null
shake_enabled = null
shake_strength = null
shake_recovery_speed = null
zoom_ratio = null
[node name="FGSprite2D" parent="Ground/ParallaxForeground/FGParallaxLayer" index="0"] [node name="FGSprite2D" parent="Ground/ParallaxForeground/FGParallaxLayer" index="0"]
texture = null texture = null

View File

@ -22,9 +22,9 @@ size = Vector2(40, 70)
[node name="S03" type="Node2D"] [node name="S03" type="Node2D"]
[node name="Ground" parent="." node_paths=PackedStringArray("camera_focus_marker") instance=ExtResource("1_lheeb")] [node name="Ground" parent="." instance=ExtResource("1_lheeb")]
scene_name = "c02_s03" scene_name = "c02_s03"
camera_focus_marker = NodePath("MainPlayer/CameraFocusMarker") player_y = 60
[node name="AnimationPlayer" parent="Ground" index="0"] [node name="AnimationPlayer" parent="Ground" index="0"]
script = ExtResource("2_l2oec") script = ExtResource("2_l2oec")
@ -74,7 +74,18 @@ ambient_light_energy = 2.0
position = Vector2(1120, 5) position = Vector2(1120, 5)
[node name="MainPlayer" parent="Ground" index="5"] [node name="MainPlayer" parent="Ground" index="5"]
position = Vector2(25, 88) position = Vector2(25, 98)
[node name="CameraFocusMarker" parent="Ground" index="6"]
force_offset = null
lock_horizontal = null
speed = null
half_screen_size = null
shaded_height = null
shake_enabled = null
shake_strength = null
shake_recovery_speed = null
zoom_ratio = null
[node name="BGParallaxLayer" parent="Ground/ParallaxForeground" index="0"] [node name="BGParallaxLayer" parent="Ground/ParallaxForeground" index="0"]
use_parent_material = true use_parent_material = true
@ -88,8 +99,8 @@ texture = ExtResource("7_icddm")
position = Vector2(-12, -143) position = Vector2(-12, -143)
scale = Vector2(1.08, 1.08) scale = Vector2(1.08, 1.08)
[node name="DirectionalLight2D" parent="Ground" index="8"] [node name="DirectionalLight2D" parent="Ground" index="9"]
color = Color(0.368627, 0.447059, 0.882353, 1) color = Color(0.688281, 0.748391, 0.96674, 1)
[editable path="Ground"] [editable path="Ground"]
[editable path="Ground/DeployLayer/Ambush"] [editable path="Ground/DeployLayer/Ambush"]

View File

@ -62,7 +62,6 @@ func _ready() -> void:
return return
footstep_timer.timeout.connect(_on_footstep_timer_timeout) footstep_timer.timeout.connect(_on_footstep_timer_timeout)
footstep_timer.stop() footstep_timer.stop()
# SceneManager.focus_player(self)
_check_character_status() _check_character_status()

View File

@ -27,7 +27,7 @@ var ANIMATION_CONFIG = {
MOVEMENT_WALKING: [&"c00_吕萍_walking_left", &"c00_吕萍_walking_right"], MOVEMENT_WALKING: [&"c00_吕萍_walking_left", &"c00_吕萍_walking_right"],
MOVEMENT_RUNNING: [&"c00_吕萍_running_left", &"c00_吕萍_running_right"], MOVEMENT_RUNNING: [&"c00_吕萍_running_left", &"c00_吕萍_running_right"],
# animation_name, scale, offset # animation_name, scale, offset
ACTION_LOOKUP_WALL: [&"c00_吕萍_记笔记_right", Vector2(1.2, 1.2), Vector2(0, 0)], # ACTION_LOOKUP_WALL: [&"c00_吕萍_记笔记_right", Vector2(1.2, 1.2), Vector2(0, -50)],
}, },
"吕萍爬行": "吕萍爬行":
{ {