千里之行,始于足下
零、 笔记
本文将制作这个系列里的第一个UI(User Interface,用户界面)——时钟UI,如下图所示;
一、UI界面
时钟面板 时钟面板 时钟面板
第一步,在 res://场景/UI/ 路径 下,创建 时钟UI.tscn 场景;
节点树如下:
- 时钟UI(Control)
- 时钟面板(PanelContainer)
- 昼夜图标1(Sprite2D)
- 昼夜图标2(Sprite2D)
- 当前时间(Label)
- 时钟面板(PanelContainer)
第二步,选中 时钟面板 节点,在检查器中 新建Theme 并另存为 游戏UI主题.tres 到路径 res://资源/主题/ 下;
第三步,在展开的主题底栏中点击【+】,添加项目类型 ClockUI ;
第四步,添加基础类型 PanelContainer ;
第五步,在panel下新建 StyleBoxTexture 并选中,随后在检查器中新建 AtlasTexture ;
第六步,从文末 UI包 导入 Weather_UI_Free.png,并 编辑区域 ;
第七步,观察到裁剪后图片尺寸为 65x54像素;
第八步,选中时钟面板节点,在检查器中更改 size 为 65x54 ,更改 Type Variation 为 ClockUI ;
效果如下;
昼夜图标 1 (左) 昼夜图标1(左) 昼夜图标1(左)
第一步,选中昼夜图标(Sprite2D)节点,直接将 UI包 中的 Weather_Icons_smal_freel.png拖入检查器中的 Texture ;
第二步,点开检查器中的 Animation ,并设置 Hframes 为 2,Vframes 为 3 ;
第三步,手动将图标拖入时钟UI中,如下图;
昼夜图标 2 (右) 昼夜图标2(右) 昼夜图标2(右)
第一步,选中昼夜图标(Sprite2D)节点,在检查器中新建 AtlasTexture ;
第二步,从文末 UI包 中导入 Weather_UI_Free.png,并 编辑区域 ;
第三步,手动将图标拖入时钟UI中,如下图;
当前时间 当前时间 当前时间
第一步,选中 当前时间 节点,加载 游戏UI主题.tres 主题;
第二步,在展开的主题底栏中,点击【+】按钮,添加项目类型 CurrentTime ;
第三步,设置基础类型为 Label ,字体大小 font_size 为 16 ,字体为 UI包 中的 pixelFont-7-8x14-sproutLands.ttf ;
第四步,调整 当前时间 节点至合适的位置;
第五步,以 游戏UI(CanvasLayer) 为根节点,新建场景 游戏ui.tscn ,并保存在 res://场景/UI/ 路径下;
第六步,添加 MarginContainer 为子节点,并实例化 时钟UI 为其子节点;
节点树如下:
- 游戏UI
- MarginContainer
- 时钟UI
- MarginContainer
第七步,选中MarginContainer节点,在检查器中调整参数如下;
锚点预设 右上 ,尺寸大小为 70x59 ——时钟UI长宽各自增加 5;
上外边距(Margin Top)、右外边距(Margin Right)设置为 5 ;
此时运行游戏UI场景,时钟UI应该与 右边框 和 上边框 各自有5个像素的距离;
二、脚本
第一步,选中 时钟UI 节点,附加脚本;
extends Control
## 时钟UI面板,00:00 -> 23:59 循环更替
## 6点 太阳
## 18点 月亮
@onready var 当前时间: Label = $"当前时间"
@onready var 昼夜图标1: Sprite2D = $"时钟面板/昼夜图标1"
func _ready() -> void:
TimeManager.游戏格式化时间更新.connect(时间更新)
func 时间更新(时间: Array[int]) ->void:
当前时间.text = "%02d:%02d" % [时间[1], 时间[2]]
# 更新昼夜图标
if 时间[1] == 18:
昼夜图标1.frame = 2 # 夜晚
elif 时间[1] == 6:
昼夜图标1.frame = 0 # 白天
第二步,创建 时间管理器 单例,前文 Godot4.3类星露谷游戏开发之【昼夜循环】中已经实现;
extends Node
## 时间管理
signal 游戏总时间更新(秒: float)
signal 游戏格式化时间更新(天:int, 时: int, 分: int, 秒: int)
const 每日秒数: int = 24 * 60 * 60
const 每时秒数: int = 60 * 60
const 每分秒数: int = 60
const 时间单元: Array[Array] = [
[每日秒数, "天"],
[每时秒数, "小时"],
[每分秒数, "分钟"],
[1, "秒"],
]
# 初始游戏时间,第1天6:00:00
var 初始游戏天数: int = 1
var 初始游戏小时数: int = 6
var 初始游戏分钟数: int = 0
var 初始游戏秒数: int = 0
# 累计游戏时间
var 累计游戏时间: float = 0.0
# 其他设置
var 时间流速: float = 7000.0 # 相当于正常时间流速的5000倍
var 时间暂停: bool = false
# 初始化累计游戏时间
func _ready() -> void:
累计游戏时间 = 计算初始总秒数()
# 产生时间
func _process(delta: float) -> void:
if 时间暂停:
return
累计游戏时间 += delta * 时间流速
#print_debug("累计游戏时间:", 累计游戏时间)
# 发送时间信号
游戏总时间更新.emit(累计游戏时间)
# 转换格式并发送时间信号
var 格式化时间: Array[int] = 转换时间格式(int(累计游戏时间))
游戏格式化时间更新.emit(格式化时间)
# 计算初始时间总秒数
func 计算初始总秒数() ->float:
return (
初始游戏天数 * 每日秒数 +
初始游戏小时数 * 每时秒数 +
初始游戏分钟数 * 每分秒数 +
初始游戏秒数
)
# 格式转换:总秒数 -> 日/时/分/秒
func 转换时间格式(总秒数: int) ->Array[int]:
# 异常处理
if 总秒数 < 0:
push_error("无效的时间参数")
return [0, 0, 0, 0]
# 格式转换
var 剩余秒数 = int(总秒数)
var 结果:Array[int] = []
for 单元 in 时间单元:
var 值 = 剩余秒数 / 单元[0]
剩余秒数 %= 单元[0]
结果.append(值)
print_debug(结果)
return 结果
三、搭建测试环境
在前文 Godot4.3类星露谷游戏开发之【昼夜循环】创建的 测试_昼夜循环 场景中 ,实例化 游戏UI 场景为节点 ;
四、测试
运行 测试_昼夜循环 场景,测试时钟UI走动效果;
测试完成!
五、免费开源资产包
进入链接后点击下图按钮;
然后点击【No thanks,just take me to the downloads】(不了谢谢,只想下载);
最后点击下图按钮完成下载(注意导入前需解压缩)。