Godot游戏练习01-第14节-Theme,字体,游戏UI

今天来学习游戏中的主题(Theme)和字体调整, 并添加一个能显示轮次和倒计时的游戏UI

看看效果

像素字体加上, 瞬间有那感觉了! 有点那么回事了, 哈哈

anim1.gif

实现过程

主题和字体设置

字体我是直接在网上找了一个开源字体, 觉得好看就用了: https://github.com/TakWolf/fusion-pixel-font

下载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显示一致

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容