@ -3,6 +3,14 @@ class_name PropHud extends Control
signal current_item_changed ( prop_key : String )
# 常量定义
const PROP_CONTAINER_X = 130.0
const PROP_CONTROL_X = 110.0
const TWEEN_DURATION = 0.5
const SHAKE_FPS = 15.0
const SHAKE_DURATION = 0.8
const SHAKE_DELTA = 12.0
@ export_group ( " DebugItem " )
@ export var enable_item : = false :
set ( value ) :
@ -10,12 +18,18 @@ signal current_item_changed(prop_key: String)
enable_item = false
enable_prop_item ( item_key )
@ export var item_key : String
@ export_group ( " Inventory " )
@ export var inventory : PropInventory :
set ( value ) :
if inventory == value :
return
if inventory and inventory . current_item_changed . is_connected ( _emit_changed ) :
inventory . current_item_changed . disconnect ( _emit_changed )
inventory = value
if inventory and not inventory . current_item_changed . is_connected ( _emit_changed ) :
inventory . current_item_changed . connect ( _emit_changed )
@ export_group ( " UI-UX " )
@ export var display_time : = 2.5 # 不包含渐入渐出(约 0.6s)的时长
@ export var locked : = false :
@ -45,10 +59,8 @@ signal current_item_changed(prop_key: String)
@ onready var props_bag_scroll = % PropsBagScroll as ScrollContainer
@ onready var props_bag = % PropsBag as HBoxContainer
@ onready var select_mark = % SelectMark as TextureRect
var prop_containers = [ ] #CenterContainer
const PROP_CONTAINER_X = 130.0
const PROP_CONTROL_X = 110.0
var prop_containers : Array [ CenterContainer ] = [ ]
var items_dict : = { }
var items_description_dict = { }
# 从配置文件加载 prop items
@ -62,10 +74,16 @@ var displaying = false
var timer : = Timer . new ( )
var display_tween : Tween
var container_tween : Tween
var prop_blink : Tween
var tween_scroll : Tween
var shake_tween : Tween
# hud 是否监听快捷键
var listening_hotkey = true
# 缓存的占位符纹理
var placeholder_texture : Texture2D
func _emit_changed ( prop_key : = " " ) :
if not selected :
@ -77,33 +95,43 @@ func _emit_changed(prop_key := ""):
func _ready ( ) - > void :
if Engine . is_editor_hint ( ) :
return
# 初始化占位符纹理
placeholder_texture = preload ( " res://asset/art/ui/hud/placeholder.png " )
# read prop containers
for id in range ( props_bag . get_child_count ( ) ) :
var container = props_bag . get_child ( id )
prop_containers . append ( container )
container . get_child ( 0 ) . get_child ( 0 ) . gui_input . connect ( _on_prop_gui_input . bind ( id ) )
var button = container . get_child ( 0 ) . get_child ( 0 )
if button :
button . gui_input . connect ( _on_prop_gui_input . bind ( id ) )
display_prop . gui_input . connect ( _on_prop_gui_input . bind ( - 1 ) )
_load_items_config_to_dict ( " ImportantPropItems " )
_load_items_config_to_dict ( " PropItems " )
_reload_cache_and_realign_display ( )
selecting_bg . modulate . a = 0.0
prop_scroll . scroll_horizontal = PROP_CONTAINER_X
props_bag_scroll . scroll_horizontal = 0.0
props_bag_scroll . custom_minimum_size . x = 0.0
# focus_exited.connect(_on_focus_exited)
# 存档更新时,从存档加载 prop
ArchiveManager . archive_loaded . connect ( _reload_cache_and_realign_display )
# tween timer
timer . wait_time = display_time
timer . one_shot = true
timer . autostart = false
timer . timeout . connect ( _on_timer_timeout )
add_child ( timer )
# connect signals
left_btn . pressed . connect ( on_left_pressed )
right_btn . pressed . connect ( on_right_pressed )
title_label . modulate . a = 0.0
# _toggle_btn_ability(false)
left_btn . modulate . a = 0.5
right_btn . modulate . a = 0.5
mouse_entered . connect ( _on_mouse_entered )
@ -111,51 +139,36 @@ func _ready() -> void:
func _load_items_config_to_dict ( title : String ) :
if not item_config_res or not item_config_res . titles . has ( title ) :
return
var id = item_config_res . titles [ title ]
var current_line = item_config_res . lines [ id ]
var current_line = item_config_res . lines . get ( id )
while current_line :
if current_line . has ( " tags " ) and current_line . has ( " translation_key " ) :
var wrapped_texture : = " texture= "
var wrapped_inspect : = " inspect= "
var texture_path = " "
var inspect_path = " "
for t in current_line . tags :
if t . begins_with ( wrapped_texture ) :
texture_path = t . replace ( wrapped_texture , " " ) . strip_edges ( )
elif t . begins_with ( wrapped_inspect ) :
inspect_path = t . replace ( wrapped_inspect , " " ) . strip_edges ( )
for tag in current_line . tags :
if tag . begins_with ( " texture= " ) :
texture_path = tag . substr ( 8 ) . strip_edges ( )
elif tag . begins_with ( " inspect= " ) :
inspect_path = tag . substr ( 8 ) . strip_edges ( )
var item = PropItem . new ( )
item . key = current_line . translation_key
if texture_path :
item . texture_path = path_prefix + texture_path
if inspect_path :
item . inspect_path = path_prefix + inspect_path
items_dict [ item . key ] = item
# # 检查是否是重要物品,如果是,则添加到 items_description_dict
items_description_dict [ item . key ] = tr ( item . key + " _说明 " ) . replace ( " {br} " , " \n " )
# if item_config_res.titles.has(item.key):
# var important_item_line_id = item_config_res.titles[item.key]
# items_description_dict[item.key] = get_import_item_content(important_item_line_id)
if not current_line . has ( " next_id " ) or current_line . next_id == " end " :
break
current_line = item_config_res . lines [ current_line . next_id ]
# func get_import_item_content(line_id) -> String:
# var current_line = item_config_res.lines[line_id]
# var content = ""
# while current_line:
# if current_line.has("text"):
# if current_line.has("translation_key"):
# content += tr(current_line.translation_key) + "\n"
# else:
# content += current_line.text + "\n"
# if not current_line.has("next_id") or current_line.next_id == "end":
# break
# current_line = item_config_res.lines[current_line.next_id]
# content.replace("{br}", "\n")
# return content
current_line = item_config_res . lines . get ( current_line . next_id )
func _reload_cache_and_realign_display ( ) - > void :
@ -174,57 +187,90 @@ func checkout_inventory(character: String) -> void:
_reload_cache_and_realign_display ( )
func hide_hud ( ) :
# 隐藏 hud 并静音
hide ( )
const HUD_FADE_DURATION = 0.3
# 在变量定义区域添加
var hud_visibility_tween : Tween
func hide_hud ( duration : float = HUD_FADE_DURATION ) :
if not visible :
return
listening_hotkey = false
# 清理之前的补间动画
if hud_visibility_tween and hud_visibility_tween . is_running ( ) :
hud_visibility_tween . kill ( )
# 创建渐变动画
hud_visibility_tween = create_tween ( )
hud_visibility_tween . tween_property ( self , " modulate:a " , 0.0 , duration )
hud_visibility_tween . tween_callback ( hide )
func display_hud ( ) :
# 显示 hud 并取消静音
show ( )
listening_hotkey = true
func display_hud ( duration : float = HUD_FADE_DURATION ) :
if visible and modulate . a > = 1.0 :
return
# 清理之前的补间动画
if hud_visibility_tween and hud_visibility_tween . is_running ( ) :
hud_visibility_tween . kill ( )
# 确保节点可见但透明
if not visible :
modulate . a = 0.0
show ( )
# 创建渐变动画
hud_visibility_tween = create_tween ( )
hud_visibility_tween . tween_property ( self , " modulate:a " , 1.0 , duration )
hud_visibility_tween . tween_callback ( func ( ) : listening_hotkey = true )
func _load_texture_cache ( ) - > void :
if not inventory :
return
# 移除无效纹理
var keys_to_remove = [ ]
for k in cached_inventory_textures :
# remove invalid textures
if not k in inventory . enabled_items :
cached_inventory_textures . erase ( k )
keys_to_remove . append ( k )
for k in keys_to_remove :
cached_inventory_textures . erase ( k )
# 加载新纹理
for key in inventory . enabled_items :
if cached_inventory_textures . has ( key ) :
continue
# 以 items_dict 为准,如果 enabled_items 中的 key 不存在,则删除
if not key in items_dict :
if not items_dict. has ( key ) :
inventory . disable_item ( key )
printerr (
" PropHud _load_texture_cache: key not found in items_dict: " , key , " . remove item. "
)
continue
var path = items_dict [ key ] . texture_path
if not path :
var placeholder = preload ( " res://asset/art/ui/hud/placeholder.png " )
cached_inventory_textures [ key ] = placeholder
cached_inventory_textures [ key ] = placeholder_texture
print ( " Cache load prop placeholder key= " , key )
continue
var texture = load ( path ) as Texture2D
if texture :
if GlobalConfig . DEBUG :
print ( " Cache load prop texture key= " , key )
cached_inventory_textures [ key ] = texture
# wrap index
inventory . current_index = wrapi ( inventory . current_index , 0 , inventory . enabled_items . size ( ) )
if inventory . enabled_items . size ( ) > 0 :
inventory . current_index = wrapi ( inventory . current_index , 0 , inventory . enabled_items . size ( ) )
func _update_prop_display_with_texture ( ) :
if not inventory :
return
var key = " "
# 在没有道具时,展示空手 placeholder
if inventory . enabled_items . is_empty ( ) :
display_prop . texture_normal = preload ( " res://asset/art/ui/hud/placeholder.png " )
display_prop . texture_normal = placeholder_texture
display_prop . size = Vector2 ( PROP_CONTROL_X , PROP_CONTROL_X )
display_prop . scale = Vector2 ( 1.0 , 1.0 )
title_label . text = tr ( " prop_空手 " )
@ -232,36 +278,48 @@ func _update_prop_display_with_texture():
key = inventory . current_item_key ( )
_display_texture_by_key ( display_prop , key )
title_label . text = tr ( key )
# 如果当前是 prop_小猫玩具完整, 尝试点亮玩家的灯效; 否则无需点亮
var player = SceneManager . get_player ( )
if player :
player . set_catty_light ( key == " prop_小猫玩具完整 " )
if GlobalConfig . DEBUG :
print ( " [PropHud] current display prop: " , key )
# 选中标记 select_mark; 如果被 free 掉,则重新创建
if select_mark and is_instance_valid ( select_mark ) :
var parent = select_mark . get_parent ( )
if parent :
parent . remove_child ( select_mark )
else :
select_mark = TextureRect . new ( )
select_mark . custom_minimum_size = Vector2 ( PROP_CONTAINER_X , PROP_CONTAINER_X )
select_mark . texture = preload ( " res://asset/art/ui/hud/select_mark.png " )
# bag
# 选中标记处理
_update_select_mark ( )
# bag更新
for i in range ( inventory . enabled_items . size ( ) ) :
var id = wrapi ( i , 0 , inventory . enabled_items . size ( ) )
var k = inventory . enabled_items [ id ]
var button = prop_containers [ i ] . get_child ( 0 ) . get_child ( 0 ) as TextureButton
var container = prop_containers [ i ]
var button = container . get_child ( 0 ) . get_child ( 0 ) as TextureButton
_display_texture_by_key ( button , k )
if id == inventory . current_index :
prop_containers [ i ] . get_child ( 0 ) . add_child ( select_mark )
container . get_child ( 0 ) . add_child ( select_mark )
prop_scroll . scroll_horizontal = PROP_CONTAINER_X
# props_bag_scroll.scroll_horizontal = 0.0
func _display_texture_by_key ( button , key ) - > void :
if not key :
button . texture_normal = null
func _update_select_mark ( ) :
if not is_instance_valid ( select_mark ) :
select_mark = TextureRect . new ( )
select_mark . custom_minimum_size = Vector2 ( PROP_CONTAINER_X , PROP_CONTAINER_X )
select_mark . texture = preload ( " res://asset/art/ui/hud/select_mark.png " )
else :
var parent = select_mark . get_parent ( )
if parent :
parent . remove_child ( select_mark )
func _display_texture_by_key ( button : TextureButton , key : String ) - > void :
if not key or not button :
if button :
button . texture_normal = null
return
if not items_dict . has ( key ) :
return
var item = items_dict [ key ]
var texture = cached_inventory_textures . get ( item . key )
@ -270,14 +328,15 @@ func _display_texture_by_key(button, key) -> void:
texture = load ( item . texture_path ) as Texture2D
if not texture :
printerr ( " PropHud _display_texture_by_key: No texture found for item: " , item )
return
else :
cached_inventory_textures [ item . key ] = texture
button . texture_normal = texture
var t_size = button. texture_normal . get_size ( )
var max_ x = max ( t_size . x , t_size . y )
var t_size = texture. get_size ( )
var max_ dimension = max ( t_size . x , t_size . y )
var p_scale = min ( PROP_CONTROL_X / t_size . x , PROP_CONTROL_X / t_size . y )
button . scale = Vector2 ( p_scale , p_scale )
button . size = Vector2 ( max_ x, max_x )
button . size = Vector2 ( max_ dimension, max_dimension )
func on_left_pressed ( ) - > void :
@ -305,34 +364,37 @@ func on_right_pressed() -> void:
func _tween_container ( left_to_right : = true ) - > void :
if container_tween and container_tween . is_running ( ) :
container_tween . kill ( )
container_tween = create_tween ( )
if left_to_right :
prop_scroll . scroll_horizontal = 2 * PROP_CONTAINER_X
else :
prop_scroll . scroll_horizontal = 0.0
# 通过 Head 与 Tail 占位符,实现滚动效果;否则会导致卡在边界上,无法滚动
prop_scroll . scroll_horizontal = 2 * PROP_CONTAINER_X if left_to_right else 0.0
container_tween . tween_property ( prop_scroll , " scroll_horizontal " , PROP_CONTAINER_X , 0.2 )
func _on_prop_gui_input ( event : InputEvent , id ) - > void :
if locked :
func _on_prop_gui_input ( event : InputEvent , id : int ) - > void :
if locked or not event is InputEventMouseButton :
return
if event is InputEventMouseButton and event . is_pressed ( ) :
event = event as InputEventMouseButton
if event . button_index == MOUSE_BUTTON_LEFT :
var mouse_event = event as InputEventMouseButton
if not mouse_event . is_pressed ( ) :
return
match mouse_event . button_index :
MOUSE_BUTTON_LEFT :
_on_prop_pressed ( id )
elif event . button_index == MOUSE_BUTTON_RIGHT :
MOUSE_BUTTON_RIGHT :
_on_prop_inspected ( id )
func _on_prop_inspected ( id : = 0 ) - > void :
if locked :
return
var prop_key = " "
if id > = 0 :
if id > = 0 and id < inventory . enabled_items . size ( ) :
prop_key = inventory . enabled_items [ id ]
else :
prop_key = inventory . current_item_key ( )
if prop_key :
sfx_inspect . play ( )
print ( " [PropHud] inspect prop: " , prop_key )
@ -342,37 +404,37 @@ func _on_prop_inspected(id := 0) -> void:
func _on_prop_pressed ( id : = 0 ) - > void :
if locked :
return
sfx_click . play ( )
if GlobalConfig . DEBUG :
print ( " PropHUD Panel pressed. " )
focus_mode = FOCUS_ALL
grab_focus ( )
selected = true
if id > = 0 :
if id > = 0 and id < inventory . enabled_items . size ( ) :
inventory . current_index = id
_update_prop_display_with_texture ( )
_mouse_moved_on_listening ( true )
var prop_blink : Tween
var tween_scroll : Tween
func _toggle_scroll ( fold : = true ) - > void :
if prop_blink and prop_blink . is_running ( ) :
prop_blink . kill ( )
if tween_scroll and tween_scroll . is_running ( ) :
tween_scroll . kill ( )
# PROP_CONTAINER_X + 10. 为hud的两侧留出的空间
if fold :
# kill blink
select_mark . modulate . a = 1.0
selecting_bg . modulate . a = 0.0
# fold
tween_scroll = create_tween ( )
tween_scroll . tween_property ( props_bag_scroll , " custom_minimum_size:x " , 0.0 , 0.5 )
tween_scroll . tween_property ( props_bag_scroll , " custom_minimum_size:x " , 0.0 , TWEEN_DURATION )
tween_scroll . parallel ( ) . tween_property (
hud_rect , " custom_minimum_size:x " , PROP_CONTAINER_X + 10. , 0.5
hud_rect , " custom_minimum_size:x " , PROP_CONTAINER_X + 10. , TWEEN_DURATION
)
else :
# blink
@ -388,12 +450,17 @@ func _toggle_scroll(fold := true) -> void:
prop_blink . parallel ( ) . tween_property ( selecting_bg , " modulate:a " , . 6 , 1. ) . set_ease (
Tween . EASE_IN_OUT
)
# unfold
var bag_x = prop_containers . size ( ) * PROP_CONTAINER_X
var hud_x = bag_x + PROP_CONTAINER_X + 10.
tween_scroll = create_tween ( )
tween_scroll . tween_property ( props_bag_scroll , " custom_minimum_size:x " , bag_x , 0.5 )
tween_scroll . parallel ( ) . tween_property ( hud_rect , " custom_minimum_size:x " , hud_x , 0.5 )
tween_scroll . tween_property (
props_bag_scroll , " custom_minimum_size:x " , bag_x , TWEEN_DURATION
)
tween_scroll . parallel ( ) . tween_property (
hud_rect , " custom_minimum_size:x " , hud_x , TWEEN_DURATION
)
func _on_mouse_entered ( ) - > void :
@ -410,9 +477,11 @@ func _on_mouse_exited() -> void:
func _mouse_moved_on_listening ( unfold_scroll : = false ) - > void :
if unfold_scroll :
_toggle_scroll ( false )
if not displaying :
_toggle_details ( true )
return
timer . start ( display_time )
@ -424,6 +493,7 @@ func _on_timer_timeout() -> void:
func _unhandled_input ( event : InputEvent ) - > void :
if locked or not listening_hotkey :
return
if event . is_action_pressed ( " prop_left " ) :
on_left_pressed ( )
get_viewport ( ) . set_input_as_handled ( )
@ -431,17 +501,21 @@ func _unhandled_input(event: InputEvent) -> void:
on_right_pressed ( )
get_viewport ( ) . set_input_as_handled ( )
elif event is InputEventMouseButton :
if event . button_index == MOUSE_BUTTON_WHEEL_DOWN and event . pressed :
on_left_pressed ( )
get_viewport ( ) . set_input_as_handled ( )
elif event . button_index == MOUSE_BUTTON_WHEEL_UP and event . pressed :
on_right_pressed ( )
get_viewport ( ) . set_input_as_handled ( )
var mouse_event = event as InputEventMouseButton
if mouse_event . pressed :
match mouse_event . button_index :
MOUSE_BUTTON_WHEEL_DOWN :
on_left_pressed ( )
get_viewport ( ) . set_input_as_handled ( )
MOUSE_BUTTON_WHEEL_UP :
on_right_pressed ( )
get_viewport ( ) . set_input_as_handled ( )
func _input ( event : InputEvent ) - > void :
if locked :
return
if listen_mouse and ( event is InputEventMouseMotion or event is InputEventScreenTouch ) :
_mouse_moved_on_listening ( )
@ -462,7 +536,6 @@ func _toggle_details(display := true) -> void:
display_tween . parallel ( ) . tween_property ( title_label , " modulate:a " , 0.0 , 0.6 )
display_tween . parallel ( ) . tween_property ( left_btn , " modulate:a " , 0.5 , 0.5 )
display_tween . parallel ( ) . tween_property ( right_btn , " modulate:a " , 0.5 , 0.5 )
# display_tween.tween_callback(_toggle_btn_ability.bind(false))
timer . stop ( )
@ -474,11 +547,14 @@ func _toggle_btn_ability(v: bool) -> void:
func enable_important_item ( prop_key : String , display_inspector : bool ) - > void :
if not inventory or not prop_key :
return
if not items_dict . has ( prop_key ) :
push_error ( " ImportantPropItem not found! key= " + prop_key )
return
inventory . enable_important_item ( prop_key )
SceneManager . pop_notification ( " ui_notify_important_item_update " )
if display_inspector :
sfx_inspect . play ( )
inspect_item ( prop_key , true , true )
@ -488,13 +564,17 @@ func enable_prop_item(prop_key: String, inspect := true) -> void:
if not inventory or not prop_key :
printerr ( " PropHUD Enable prop item: No inventory or prop_key provided. " )
return
if not items_dict . has ( prop_key ) :
push_error ( " PropItem not found! key= " + prop_key )
return
inventory . enable_item ( prop_key )
_reload_cache_and_realign_display ( )
if GlobalConfig . DEBUG :
print ( " PropHUD Enable prop item: " , prop_key )
if inspect :
sfx_new_prop . play ( )
inspect_item ( prop_key )
@ -502,27 +582,31 @@ func enable_prop_item(prop_key: String, inspect := true) -> void:
func inspect_item ( prop_key : String , display_obtained : = true , as_important_item : = false ) :
var inspector = SceneManager . get_inspector ( )
if inspector :
var texture_path = items_dict [ prop_key ] . texture_path
var inspect_path = items_dict [ prop_key ] . inspect_path
# 是否有独立的 inspect 图片
if inspect_path :
var texture = load ( inspect_path ) as Texture2D
inspector . pop_prop_inspection (
prop_key , texture , false , display_obtained , as_important_item
)
else :
var texture = cached_inventory_textures . get ( prop_key )
if not texture :
texture = load ( texture_path ) as Texture2D
if texture :
cached_inventory_textures [ prop_key ] = texture
else :
printerr ( " prophud inspect_item invalid texture_path: " , texture_path )
return
inspector . pop_prop_inspection (
prop_key , texture , true , display_obtained , as_important_item
)
if not inspector or not items_dict . has ( prop_key ) :
return
var item = items_dict [ prop_key ]
var texture : Texture2D = null
var is_inspect_texture = false
# 检查是否有独立的 inspect 图片
if item . inspect_path :
texture = load ( item . inspect_path ) as Texture2D
is_inspect_texture = true
else :
texture = cached_inventory_textures . get ( prop_key )
if not texture and item . texture_path :
texture = load ( item . texture_path ) as Texture2D
if texture :
cached_inventory_textures [ prop_key ] = texture
if not texture :
printerr ( " prophud inspect_item invalid texture for key: " , prop_key )
return
inspector . pop_prop_inspection (
prop_key , texture , not is_inspect_texture , display_obtained , as_important_item
)
func disable_prop_item ( prop_key : String ) - > void :
@ -533,16 +617,21 @@ func disable_prop_item(prop_key: String) -> void:
func _align_container_size ( ) - > void :
# 判断是否需要添加新的 prop container
if not inventory :
return
# 添加新容器
while inventory . enabled_items . size ( ) > prop_containers . size ( ) :
append_prop_container ( )
# 判断是否需要删除 prop container, 不保留余数
# 删除多余容器
while inventory . enabled_items . size ( ) < prop_containers . size ( ) :
remove_prop_container ( )
if displaying :
_mouse_moved_on_listening ( )
# 如果正在展示,则更新 scroll 长度
if displaying and props_bag_scroll. custom_minimum_size . x > 0.0 :
if props_bag_scroll. custom_minimum_size . x > 0.0 :
_toggle_scroll ( false )
@ -550,58 +639,65 @@ func append_prop_container() -> void:
var container = CenterContainer . new ( )
container . custom_minimum_size = Vector2 ( PROP_CONTAINER_X , PROP_CONTAINER_X )
container . set_anchors_preset ( Control . PRESET_FULL_RECT )
prop_containers . append ( container )
var control = Control . new ( )
control . custom_minimum_size = Vector2 ( PROP_CONTROL_X , PROP_CONTROL_X )
control . set_anchors_preset ( Control . PRESET_FULL_RECT )
container . add_child ( control )
var prop = TextureButton . new ( )
prop . stretch_mode = TextureButton . STRETCH_KEEP_ASPECT_CENTERED
control . add_child ( prop )
# 添加到 hbox: container -> control -> prop
props_bag . add_child ( container )
prop . gui_input . connect ( _on_prop_gui_input . bind ( prop_containers . size ( ) - 1 ) )
prop_containers . append ( container )
var index = prop_containers . size ( ) - 1
prop . gui_input . connect ( _on_prop_gui_input . bind ( index ) )
func remove_prop_container ( ) - > void :
if prop_containers . size( ) == 0 :
if prop_containers . is_empty( ) :
return
var container = prop_containers . pop_back ( )
props_bag . remove_child ( container )
container . queue_free ( )
if container and is_instance_valid ( container ) :
props_bag . remove_child ( container )
container . queue_free ( )
var shake_tween
# 使用无效道具,抖动提示
func on_toggle_invalid_prop ( ) :
if not inventory or not inventory . current_item_key ( ) :
return
if GlobalConfig . DEBUG :
print ( " 使用无效道具. invalid_prop shake. current prop: " , inventory . current_item_key ( ) )
if shake_tween :
if shake_tween and shake_tween . is_running ( ) :
shake_tween . kill ( )
# 抖动效果,逐渐减弱
# 抖动效果
shake_tween = create_tween ( )
var fps : = 15.0
var duration : = 0.8
var delta : = 12.0
var count = int ( SHAKE_DURATION * SHAKE_FPS )
var delta_t = 1.0 / SHAKE_FPS
var origin_pos = Vector2 . ZERO
var count = int ( duration * fps )
var delta_t = 1.0 / fps
var prop = display_prop
# var prop = prop_containers[0].get_child(0)
prop . modulate = Color ( 1.0 , 0.6 , 0.6 , 1.0 )
for i in range ( count ) :
var offset = Vector2 ( randf_range ( - delta , delta ) , randf_range ( - delta , delta ) ) * exp ( - i )
var decay = exp ( - i )
var offset = Vector2 (
randf_range ( - SHAKE_DELTA , SHAKE_DELTA ) * decay ,
randf_range ( - SHAKE_DELTA , SHAKE_DELTA ) * decay
)
shake_tween . tween_property ( prop , " position " , origin_pos + offset , delta_t ) . set_trans (
Tween . TRANS_CUBIC
)
shake_tween . tween_callback ( _reset_prop_modulate )
func _reset_prop_modulate ( ) :
var prop = display_prop
# var prop = prop_containers[0].get_child(0)
prop . modulate = Color ( 1.0 , 1.0 , 1.0 , 1.0 )
if display_prop :
display_prop . modulate = Color . WHITE