今天来学习游戏中的主题(Theme)和字体调整, 并添加一个能显示轮次和倒计时的游戏UI
看看效果
像素字体加上, 瞬间有那感觉了! 有点那么回事了, 哈哈
实现过程
主题和字体设置
字体我是直接在网上找了一个开源字体, 觉得好看就用了: github.com/TakWolf/fus…
下载otf格式, 不带woff/woff2后缀的字体, 导入Godot, 关闭抗锯齿(Antialiasing), Hinting, Subpixel Positioning后重新导入, 像素游戏不需要抗锯齿/高清/子像素等设置, 导入zh_hans(简体中文版本)
新建一个Theme资源, 命名为default.tres, 将Default Font设置为导入的字体, 调整字号为20 (自己在预览中觉得合适的大小)
设置默认主题: Project -> Project Settings -> GUI -> Theme -> Custom, 设置为刚刚新建的Theme资源, 并且可以调整默认字体导入选项
这样, 默认字体和主题都设置完毕
轮次数和轮次倒计时显示
新建一个CanvasLayer为根节点的场景, UI节点树如下
RoundTimerUI (CanvasLayer)
└── MarginContainer
└── VBoxContainer
├── RoundLabel
└── TimerLabel
调整对齐, Margin等属性, 让UI在靠顶居中的位置显示
RoundTimerUI脚本如下
extends CanvasLayer
@export var enemy_spawn_component: EnemySpawnComponent
@onready var round_label: Label = %RoundLabel
@onready var timer_label: Label = %TimerLabel
func _ready() -> void:
enemy_spawn_component.round_changed.connect(_on_round_changed)
func _process(_delta: float) -> void:
var time_left := enemy_spawn_component.get_round_time_left()
timer_label.text = str(ceili(time_left))
func _on_round_changed(round_count: int) -> void:
round_label.text = "Round %s" % round_count
它监听外部EnemySpawnComponent组件的轮次变化事件, 以及实时获取EnemySpawnComponent组件中的当前轮次剩余时间, 转换为整数显示, 更新UI
之后就是数据的通知与同步, 在这个场景中, 数据的同步显得稍微复杂一点, 它涉及到跨组件的Timer处理
主要把握好两个同步时间点:
- Round变化
- 新的Peer加入
同步内容: 主要同步Round计数, 以及当前剩余时间, 倒计时让每个Peer自己的Timer执行, 服务器只在关键点同步, 避免不必要的宽带浪费
这里主要看一下EnemySpawnComponent组件中提供的"同步"接口
func synchronize(peer_id: int = -1) -> void:
if not is_multiplayer_authority():
return
var data = {
"round_count": round_count,
"round_timer_time_left": round_timer.time_left,
"round_timer_running": not round_timer.is_stopped()
}
if peer_id < 0:
_synchronize.rpc(data)
elif peer_id > 1:
_synchronize.rpc_id(peer_id, data)
@rpc("authority", "call_remote", "reliable")
func _synchronize(data: Dictionary) -> void:
round_count = data.round_count
round_timer.wait_time = data.round_timer_time_left
if data.round_timer_running:
round_timer.start()
同步接口synchronize收集服务端信息, 并同步给其他的peer, 所以peer_id中过滤自身id(1)
synchronize在Round发生变化时与所有peer进行RPC同步; 在新peer加入时, 仅与新peer同步(传入peer_id)
对round_count字段添加getter和setter
var round_count: int = 0:
get:
return round_count
set(value):
round_count = value
round_changed.emit(value)
当每个peer上的round_count发生变化时, 都会触发各自的round_changed信号, 同步到UI界面, 保持数据与UI显示一致