场景封装
现在的项目规划可比之前要干净清晰多了,这次为了实现按钮的动画效果,使用的办法是将 Button 和 Label 这两个节点封装为一个名为AnimatedButton.tscn的节点,然后在其他场景直接挂在节点即可,封装后的按钮会自动调用已经写好的脚本,无需再另行编写代码。具体架构如下:
assets
├── Label
├── LLabel(对应左括号)
└── RLabel(对应右括号)动效代码
我就不大费周章去介绍设计思路了,直接看代码就是,现在写多了感觉代码也就那样,没什么好讲的。
在写的时候比较棘手的问题是关于两个括号的定位,当时实际运行时右括号总是要比左括号距离中心的位置远,后面研究了一下,问题有两个:一个是节点缩放后尺寸会大于容器,此时如果再使用 容器- 尺寸 的方法,相减之后会为负数;另一个是括号本身也有尺寸,右括号的距离应该加上两个括号的尺寸。
@tool
extends Button
@export var zoom := 1.2 ## 缩放比例
@export var duration := 0.1 ## 持续时间
@export var captions := "": ## 标题文本
set(v):
captions = v
if lbl:
lbl.text = v
_update_layout()
@export var brackets := "[]": ## 括号符号
set(v):
if v.length() > 1:
brackets = v
if brkts.size() >= 2:
for i in 2: brkts[i].text = v[i]
_update_layout()
@onready var lbl = $Label
@onready var brkts = [$LeftBracket, $RightBracket]
@onready var sfx = $AudioStreamPlayer
@onready var sound_select = preload("res://Assets/sounds/sfx/select.mp3")
@onready var sound_click = preload("res://Assets/sounds/sfx/click.mp3")
func _ready():
lbl.set("horizontal_alignment", HORIZONTAL_ALIGNMENT_CENTER)
lbl.set("vertical_alignment", VERTICAL_ALIGNMENT_CENTER)
lbl.modulate = Color("#cccccc")
for b in brkts: b.modulate.a = 0
_set_props()
func _set_props():
self.captions = captions
self.brackets = brackets
lbl.resized.connect(_update_layout)
resized.connect(_update_layout)
mouse_entered.connect(func():
_hover(true)
_play(sound_select)
)
mouse_exited.connect(func(): _hover(false))
pressed.connect(func(): _play(sound_click))
func _update_layout():
var txt_size = lbl.get_rect().size
lbl.position = (size - txt_size) * 0.5
lbl.pivot_offset = txt_size * 0.5
func _hover(hover: bool):
var t = create_tween().set_parallel(true).set_trans(Tween.TRANS_QUAD)
var pos = Vector2(size.x * 0.5, lbl.position.y)
var bw = brkts[0].get_rect().size.x * int(hover)
var targets = [Vector2(0, pos.y), Vector2(size.x - bw, pos.y)] if hover else [pos, pos]
t.tween_property(lbl, "modulate", Color.WHITE if hover else Color("#cccccc"), duration)
t.tween_property(lbl, "scale", Vector2.ONE * (zoom if hover else 1.0), duration)
for i in 2:
brkts[i].horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER if hover else 0
t.tween_property(brkts[i], "position", targets[i], duration).set_ease(Tween.EASE_OUT if hover else Tween.EASE_IN)
t.tween_property(brkts[i], "modulate:a", int(hover), duration * 0.6)
func _play(effect):
sfx.stream = effect
sfx.play()本文作者:晝行燈
版权声明:本文采用 CC BY-NC 4.0 协议授权
转载需注明作者及原文链接: https://mansifield.pages.dev/kr2byg/