class_name StrongBuffVisual extends Node2D const DEFAULT_FRAME_DIRECTORY := "res://assets/ui/strong_buff" @export var frame_directory := DEFAULT_FRAME_DIRECTORY @export var frames_per_second := 20.0 @export var center_offset := Vector2(0.0, -38.0) @export var effect_scale := 0.18 var _active := false var _frame_index := 0 var _frame_elapsed := 0.0 var _frames: Array[Texture2D] = [] var _sprite: Sprite2D func _ready() -> void: z_index = 1 _sprite = Sprite2D.new() _sprite.name = "StrongBuffEffect" _sprite.centered = true _sprite.position = center_offset _sprite.texture_filter = CanvasItem.TEXTURE_FILTER_NEAREST _sprite.visible = false add_child(_sprite) _load_frames() set_active(false) func _process(delta: float) -> void: if not _active or _frames.is_empty(): return _frame_elapsed += delta var frame_duration := 1.0 / maxf(1.0, frames_per_second) while _frame_elapsed >= frame_duration: _frame_elapsed -= frame_duration _frame_index = (_frame_index + 1) % _frames.size() _sprite.texture = _frames[_frame_index] func set_active(active: bool) -> void: _active = active and not _frames.is_empty() visible = _active set_process(_active) if _sprite != null: _sprite.visible = _active _sprite.position = center_offset _sprite.scale = Vector2.ONE * effect_scale if _active and _sprite.texture == null and not _frames.is_empty(): _sprite.texture = _frames[_frame_index] func is_active() -> bool: return _active func frame_count() -> int: return _frames.size() func current_effect_scale() -> float: return effect_scale func _load_frames() -> void: _frames.clear() var dir := DirAccess.open(frame_directory) if dir == null: return # 导出包内贴图在目录列表里显示为 xxx.png.import / xxx.png.remap; # 还原原名后 load() 才能命中。编辑器里原图与 .import 同时在列,需去重。 var files := PackedStringArray() dir.list_dir_begin() var file_name := dir.get_next() while not file_name.is_empty(): if not dir.current_is_dir(): var resource_name := file_name.trim_suffix(".import").trim_suffix(".remap") if resource_name.ends_with(".png") and not files.has(resource_name): files.append(resource_name) file_name = dir.get_next() dir.list_dir_end() files.sort() for path_name: String in files: var texture := load("%s/%s" % [frame_directory, path_name]) as Texture2D if texture != null: _frames.append(texture) if not _frames.is_empty() and _sprite != null: _sprite.texture = _frames[0]