添加了部分来自于BedrockWiki的文章!

This commit is contained in:
boybook
2025-03-19 22:17:04 +08:00
parent 41635cf9bb
commit c25ebf2767
558 changed files with 96136 additions and 24 deletions

View File

@@ -0,0 +1,155 @@
---
title: 最佳实践
category: 通用指南
nav_order: 2
tags:
- 指南
mentions:
- LukasPAH
- SmokeyStack
- TheItsNameless
- ThomasOrs
---
# 最佳实践
<!--@include: @/wiki/bedrock-wiki-mirror.md-->
:::tip 提示
本文内容假定您已对JSON-UI系统有一定了解。如果您是JSON-UI的新手请务必先阅读[JSON-UI介绍](/json-ui/json-ui-intro)和[JSON-UI文档](/json-ui/json-ui-documentation)。
:::
## 最大化兼容性并减少UI崩溃的可能性
JSON-UI与其他附加包系统不同因为**JSON-UI没有版本控制**。随着Mojang更新和修复JSON-UI系统您对UI所做的任何修改都可能失效。幸运的是您可以通过以下几种方法在Mojang更新原版UI时保持自定义UI的稳定性。
### 仅修改必要内容
最有效的防崩溃策略是只修改需要调整的部分。例如若只需要禁用经验条阴影,正确做法应是在资源包中向`hud_screen.json`文件添加:
```json
{
"progress_text_label": {
"shadow": false
}
}
```
这种极简修改方式能显著降低未来更新导致UI崩溃的风险同时保持文件整洁并大幅缩小体积。**若您将整个原版UI文件复制到资源包中进行修改说明您错误理解了JSON-UI的工作机制**。
### 善用修改策略
使用[wiki文档中的修改策略](/json-ui/json-ui-intro#modifications)能有效降低更新风险。例如在HUD中添加自定义元素时推荐使用修改数组操作而非直接插入控件
::: code-group
```json [正确做法]
{
"root_panel": {
"modifications": [
{
"array_name": "controls",
"operation": "insert_front",
"value": [
{
"custom_ui@namespace.custom_ui": {}
}
]
}
]
}
}
```
:::
这种策略性合并方式能提升与其他资源包的兼容性,并减少因原版控件结构调整导致的崩溃风险。
### 避免修改深层嵌套控件
修改嵌套层级过深的控件容易引发问题。推荐优先修改基础元素定义,必要时使用斜杠语法定位子控件:
::: code-group
```json [推荐修改方式]
{
"panel_with_label_and_bg/bg_image": {
"size": ["100%c", "100%c"]
},
"panel_with_label_and_bg/bg_image/label": {
"layer": -5
}
}
```
:::
### 使用单一入口点
合并自定义UI时建议集中到单个入口点。例如将多个自定义控件统一插入`root_panel`
::: code-group
```json [优化后]
{
"root_panel": {
"modifications": [
{
"array_name": "controls",
"operation": "insert_front",
"value": [
{"custom_ui_1@ns1.control1": {}},
{"custom_ui_2@ns1.control2": {}}
]
}
]
}
}
```
:::
### 避免使用原版命名空间
开发大规模UI修改时建议创建自定义[命名空间](/json-ui/json-ui-intro#namespaces)并使用前缀(如`wiki:namespace`)来防止命名冲突。通过`element@namespace.element`语法引用其他命名空间的元素。
## 性能优化指南
JSON-UI是仅次于实体的性能消耗大户。以下策略可帮助提升UI性能表现
### 减少操作符使用
[操作符](/json-ui/json-ui-intro#using-operators)会显著增加计算开销。优化示例:
```json
"$var": "(-2 * $number)" // 优于 "(2 * (-1 * $number))"
```
### 精简绑定数量
每个[绑定](/json-ui/json-ui-intro#bindings)都会产生性能开销。建议:
- 移除无效绑定
- 合并相似功能绑定
- 避免重复绑定相同数据
### 优化控件结构
通过以下方式减少控件数量:
1. 删除无用控件或添加`"ignored": true`
2. 合并相似控件
3. 使用条件渲染替代多个独立控件
::: code-group
```json [优化前]
// 5个独立图像控件
"image_1@image_template": {
"$texture": "textures/ui/example_1",
"$binding_text": "1"
}
...
```
```json [优化后]
// 单个动态图像控件
"image": {
"type": "image",
"texture": "#texture",
"bindings": [
{
"binding_type": "view",
"source_property_name": "('textures/ui/example_' + #hud_title_text_string)",
"target_property_name": "#texture"
}
]
}
```
:::
**注意**`"visible": false`不会阻止控件计算,应优先使用`"ignored": true`彻底禁用控件。
通过系统性优化可显著提升UI响应速度并降低资源消耗为玩家提供更流畅的游戏体验。

View File

@@ -0,0 +1,837 @@
---
title: JSON UI 入门指南
category: 通用
nav_order: 1
tags:
- guide
mentions:
- sermah
- KalmeMarq
- SirLich
- solvedDev
- Joelant05
- GTB3NW
- stirante
- MedicalJewel105
- r4isen1920
- shanewolf38
- LeGend077
- mark-wiemer
- TheItsNameless
- ThomasOrs
---
# JSON UI 入门指南
<!--@include: @/wiki/bedrock-wiki-mirror.md-->
## 简介
:::warning
JSON UI 已进入弃用阶段,推荐使用 [Ore UI](https://github.com/Mojang/ore-ui) 替代。请注意,任何使用 JSON UI 的附加包将在未来几年内失效。
:::
:::tip
本文概述了 JSON UI 的基础知识。如需更详细的文档,请查阅 [JSON UI 文档](/json-ui/json-ui-documentation)。
:::
游戏用户界面采用数据驱动模式,支持自定义修改。通过 JSON UI 系统,我们可以调整用户界面的渲染方式及部分交互行为。所有原版 UI 文件均存储在 `RP/ui/...` 文件夹中。
JSON UI 可能包含以下文件类型:
### 系统文件
这些是 JSON UI 的内置文件:
- `_global_variables.json` - 存储全局变量定义
- `_ui_defs.json` - 管理 UI 文件引用清单
### 屏幕文件
用于定义特定界面布局的文件:
- `hud_screen.json` - 显示包含快捷栏等游戏元素的 HUD 界面
- `inventory_screen.json` - 玩家背包界面
- 其他屏幕文件
### 模板文件
存储可复用 UI 组件的文件:
- `ui_common.json` - 包含通用组件(如设置界面的按钮模板)
- `ui_template_*.json` - 模块化组织的组件集合
## UI 定义文件
`_ui_defs.json` 通过数组形式引用所有 JSON UI 文件。
例如新增 `RP/ui/button.json``RP/my_ui/main_menu.json` 时,应如下配置:
::: code-group
```json [RP/ui/_ui_defs.json]
{
"ui_defs": ["ui/button.json", "my_ui/main_menu.json"]
}
```
:::
- 必须包含从资源包根目录开始的完整文件路径(包括 `.json` 扩展名)
- 只需声明自建文件,无需包含原版或其他第三方文件
- 支持非 `RP/ui/...` 路径的文件引用
- 可使用非 `.json` 扩展名,但文件内容必须为合法 JSON
## 全局变量
在 `_global_variables.json` 中定义变量 `"$info_text_color"`
::: code-group
```json [RP/ui/_global_variables.json]
{
"$info_text_color": [0.8, 0.8, 0.8]
}
```
:::
其他 UI 文件可调用此变量:
::: code-group
```json [vanilla/my_ui/file1.json]
{
"some_info": {
...
"text": "Hey",
"color": "$info_text_color"
}
}
```
```json [vanilla/my_ui/file2.json]
{
"info": {
...
"text": "Information",
"color": "$info_text_color"
}
}
```
:::
- 支持定义多个变量(逗号分隔)
- 全局变量为单向常量,不可跨文件修改
## 命名空间
命名空间是 UI 文件的唯一标识符,用于跨文件引用元素。每个命名空间必须具有唯一名称。
示例命名空间 `one` 中的元素:
::: code-group
```json [vanilla/ui/file_a.json]
{
"namespace": "one",
"foobar": {...}
}
```
:::
在命名空间 `two` 中引用:
::: code-group
```json [vanilla/ui/file_b.json]
{
"namespace": "two",
"fizzbuzz@one.foobar": {...}
}
```
:::
跨命名空间引用格式:
```json
"[元素名称]@[命名空间].[被引用元素]"
```
## 屏幕系统
屏幕文件包含游戏在特定场景调用的界面布局(如背包界面)。每个屏幕文件必须包含根元素供游戏直接访问。
屏幕文件具有数据访问隔离特性。
## UI 元素
UI 元素是 JSON UI 的基本组成单元,每个命名空间内的元素名称必须唯一。
示例文本元素:
::: code-group
```json [vanilla/ui/example_file.json]
{
"test_element": {
"type": "label",
"text": "Hello World"
}
}
```
:::
### 元素类型
常用元素类型 (`type` 属性值)
- `label` - 文本对象
- `image` - 图像渲染
- `button` - 交互按钮
- `panel` - 层叠容器
- `stack_panel` - 流式布局容器
- `grid` - 网格模板渲染
- `factory` - 动态元素生成器
- `custom` - 自定义渲染器
- `screen` - 根屏幕元素
## 动画系统
使用 `anim_type` 属性创建动画元素,可通过 `anims` 数组应用于其他元素。
示例动画元素:
::: code-group
```json [vanilla/ui/example_file.json]
{
"namespace": "example_nm",
"anim_size": {
"anim_type": "size",
"easing": "linear",
"from": [ "100%", 27 ],
"to": [ "100% + 3px", 30 ],
"duration": 1.25
},
"anim_alpha": {
"anim_type": "alpha",
"easing": "linear",
"from": 1,
"to": 0.5,
"duration": 2
},
"test_animated_element": {
...
"anims": [
"@example_nm.anim_size",
"@example_nm.anim_alpha"
]
}
}
```
:::
### 动画类型
支持动画类型 (`anim_type`)
- `alpha` - 透明度动画
- `offset` - 位移动画
- `size` - 尺寸动画
- `flip_book` - 翻页动画
- `uv` - UV 贴图动画
- `color` - 颜色过渡
- `wait` - 等待延时
- `aseprite_flip_book` - 精灵表动画
- `clip` - 裁剪动画
## 操作符系统
支持在属性中使用运算符,结合 `$变量` 和 `#绑定` 实现动态计算。
| 运算符 | 符号 | 示例 |
|----------------------|------|----------------------------------------------------------------------|
| 加法 | + | `"100% + 420px"` `($text + ' my')` |
| 减法 | - | `"100% - 69px"` `($index - 13)` |
| 乘法 | * | `($var * 9)` |
| 除法 | / | `(#value / 2)` |
| 等于 | = | `($var = 'text')` |
| 大于 | > | `(#value > 13)` |
| 小于 | < | `($var < 4)` |
| 大于等于 | >= | `(#value >= 2)` |
| 小于等于 | <= | `(#value <= 2)` |
| 逻辑与 | and | `($cond1 and $cond2)` |
| 逻辑或 | or | `($condA or $condB)` |
| 逻辑非 | not | `(not #flag)` |
## 变量系统
除全局变量外,支持在元素内定义局部变量。
### 变量定义
使用 `$` 前缀定义变量,支持多种数据类型:
::: code-group
```json [vanilla/ui/example_file.json]
{
"test_element": {
// 定义变量
"$array_var": [10, 10],
"$str_var": "foobar",
// 使用变量
"size": "$array_var",
"text": "$str_var",
// 动态引用模板
"controls": [
{ "foobar@$str_var": {} }
]
}
}
```
:::
### 变量继承
支持通过元素继承覆盖变量:
::: code-group
```json [vanilla/ui/example_file.json]
{
"base_element": {
"$var1": 1,
"$var2": false
},
"derived_element@base_element": {
"$var1": 2 // 覆盖父元素变量
}
}
```
:::
## 数据绑定
通过 `bindings` 实现数据源与元素的动态关联。
### 简单绑定
::: code-group
```json [vanilla/ui/example_file.json]
{
"label": {
"type": "label",
"text": "#hardtext",
"bindings": [
{
"binding_name": "#hardtext"
}
]
}
}
```
:::
### 重定向绑定
::: code-group
```json [vanilla/ui/example_file.json]
{
"label": {
"type": "label",
"text": "#display_text",
"bindings": [
{
"binding_name": "#source_data",
"binding_name_override": "#display_text"
}
]
}
}
```
:::
### 跨元素绑定
::: code-group
```json
{
"status_panel": {
"bindings": [
{
"binding_type": "view",
"source_control_name": "my_toggle",
"source_property_name": "#state",
"target_property_name": "#visible"
}
]
}
}
```
:::
## 条件渲染
通过变量和绑定实现动态显示控制。
### 变量条件
::: code-group
```json [vanilla/ui/hud_screen.json]
{
"hud_actionbar_text/actionbar_message": {
"$atext": "$actionbar_text",
"visible": "(not ($atext = 'hello world'))"
}
}
```
:::
### 工厂条件
::: code-group
```json [vanilla/ui/hud_screen.json]
{
"conditional_image": {
"type": "image",
"texture": "textures/ui/Black",
"$atext": "$actionbar_text",
"visible": "($atext = 'show_image')"
},
"image_factory": {
"type": "panel",
"factory": {
"name": "hud_actionbar_text_factory",
"control_ids": {
"hud_actionbar_text": "conditional_image@hud.conditional_image"
}
}
}
}
```
:::
通过结合操作符系统,可实现复杂的条件逻辑判断,为界面交互提供灵活的控制能力。
::: code-group
```json [vanilla/ui/hud_screen.json]
```
:::
### 使用绑定的条件渲染
根据上文提到的操作栏示例你可能会认为标题也使用变量。但实际情况并非如此。标题使用绑定bindings来获取数据如下所示。
::: code-group
```json [vanilla/ui/hud_screen.json]
{
...
"hud_title_text": {
"type": "stack_panel",
"orientation": "vertical", // 垂直排列
"offset": [ 0, -19 ], // 位置偏移
"layer": 1, // 渲染层级
"alpha": "@hud.anim_title_text_alpha_in", // 透明度动画
"propagate_alpha": true, // 透明度继承
"controls": [ // 子控件集合
{
"title_frame": {
"type": "panel", // 面板类型
"size": [ "100%", "100%cm" ], // 尺寸设置
"controls": [
{
"title_background": {
"type": "image", // 图像类型
"size": [ "100%sm + 30px", "100%sm + 6px" ], // 动态尺寸计算
"texture": "textures/ui/hud_tip_text_background", // 纹理路径
"alpha": "@hud.anim_title_background_alpha_in" // 背景透明度动画
}
},
{
"title": {
"type": "label", // 文本标签类型
"anchor_from": "top_middle", // 锚点起始位置
"anchor_to": "top_middle", // 锚点目标位置
"color": "$title_command_text_color", // 文字颜色变量
"text": "#text", // 文本内容绑定
"layer": 1, // 渲染层级
"localize": false, // 关闭本地化
"font_size": "extra_large", // 超大字号
"variables": [ // 条件变量组
{
"requires": "(not $title_shadow)", // 无阴影条件
"$show_shadow": false // 关闭阴影显示
},
{
"requires": "$title_shadow", // 启用阴影条件
"$show_shadow": true // 启用阴影显示
}
],
"shadow": "$show_shadow", // 阴影状态绑定
"text_alignment": "center", // 文本居中
"offset": [ 0, 6 ], // 位置微调
"bindings": [ // 数据绑定组
{
"binding_name": "#hud_title_text_string", // 原始绑定名
"binding_name_override": "#text", // 覆盖目标属性
"binding_type": "global" // 全局绑定类型
}
]
}
}
]
}
}
]
}
...
}
```
:::
我们需要在文本组件中添加另一个绑定对象来控制可见性。注意`#visible`属性会通过绑定直接控制元素可见性。以下示例将不会渲染"hello world"标题,但会显示其他所有标题。可在游戏中输入`/title @s title hello world`观察效果。
::: code-group
```json [vanilla/ui/hud_screen.json]
{
...
"hud_title_text": {
"type": "stack_panel",
"orientation": "vertical",
"offset": [ 0, -19 ],
"layer": 1,
"alpha": "@hud.anim_title_text_alpha_in",
"propagate_alpha": true,
"controls": [
{
"title_frame": {
"type": "panel",
"size": [ "100%", "100%cm" ],
"controls": [
{
"title_background": {
"type": "image",
"size": [ "100%sm + 30px", "100%sm + 6px" ],
"texture": "textures/ui/hud_tip_text_background",
"alpha": "@hud.anim_title_background_alpha_in"
}
},
{
"title": {
"type": "label",
"anchor_from": "top_middle",
"anchor_to": "top_middle",
"color": "$title_command_text_color",
"text": "#text",
"layer": 1,
"localize": false,
"font_size": "extra_large",
"variables": [
{
"requires": "(not $title_shadow)",
"$show_shadow": false
},
{
"requires": "$title_shadow",
"$show_shadow": true
}
],
"shadow": "$show_shadow",
"text_alignment": "center",
"offset": [ 0, 6 ],
"bindings": [
{
"binding_name": "#hud_title_text_string",
"binding_name_override": "#text",
"binding_type": "global"
},
{
"binding_type": "view", // 将此设为视图绑定
"source_property_name": "(not (#text = 'hello world'))", // 当标题文本不等于"hello world"时触发
"target_property_name": "#visible" // 根据条件覆盖可见性属性
}
]
}
}
]
}
}
]
}
...
}
```
:::
在资源包中使用非侵入式UI文件修改时应保持如下格式
::: code-group
```json [RP/ui/hud_screen.json]
{
"hud_title_text/title_frame/title": {
"modifications": [
{
"array_name": "bindings", // 目标数组名
"operation": "insert_back", // 末尾插入操作
"value": { // 新增绑定对象
"binding_type": "view",
"source_property_name": "(not (#text = 'hello world'))",
"target_property_name": "#visible"
}
}
]
}
}
```
:::
下面是一个更复杂的条件渲染示例。16x16的黑色图片仅在标题文本等于"hello world"时显示。虽然在此案例中不需要使用标题工厂title factory但如需使用UI动画则建议采用。
::: code-group
```json [RP/ui/hud_screen.json]
{
"black_conditional_image": {
"type": "image",
"texture": "textures/ui/Black", // 黑色纹理
"size": [16, 16], // 固定尺寸
"layer": 10, // 较高渲染层级
"bindings": [
{
"binding_name": "#hud_title_text_string" // 标题文本绑定
},
{
"binding_type": "view",
"source_property_name": "(#hud_title_text_string = 'hello world')", // 条件判断
"target_property_name": "#visible" // 可见性控制
}
]
},
"black_conditional_image_factory": {
"type": "panel",
"factory": {
"name": "hud_title_text_factory", // 使用标题工厂
"control_ids": {
"hud_title_text": "black_conditional_image@hud.black_conditional_image" // 控件ID映射
}
}
},
"root_panel": {
"modifications": [
{
"array_name": "controls", // 根面板控件数组
"operation": "insert_front", // 前置插入
"value": {
"black_conditional_image_factory@hud.black_conditional_image_factory": {} // 工厂实例
}
}
]
}
}
```
:::
## 字符串格式化
使用`%.#s`格式可以从字符串中截取指定长度的部分,其中`#`代表字符数量。示例:
```json
{
"label_element": {
"type": "label",
"text": "#text", // 文本绑定
"layer": 2,
"bindings": [
{
"binding_type": "global",
"binding_name": "#hud_title_text_string" // 全局标题绑定
},
{
"binding_type": "view",
"source_property_name": "('%.3s' * #hud_title_text_string)", // 截取前3个字符
"target_property_name": "#text" // 输出结果
}
]
}
}
```
假设变量`"$var": "abcdefghijklmn"`,则:
- `'%.5s' * $var` 返回 `abcde`
- `$var - ('%.7s' * $var)` 返回 `hijklm`
注意该格式的使用场景较为有限。
## 按钮映射
`button_mappings`允许重新定义控件输入与按钮行为的对应关系,支持键鼠、触屏和手柄输入。
按钮元素配置示例:
```json
{
"sample_button@common.button": {
"$pressed_button_name": "button_id", // 按钮ID变量
"button_mappings": [
{
"to_button_id": "$pressed_button_name",
"mapping_type": "pressed" // 按压映射
},
{
"from_button_id": "button.menu_ok", // 来源按钮
"to_button_id": "$pressed_button_name", // 目标按钮
"mapping_type": "focused" // 焦点状态映射
},
{
"from_button_id": "button.menu_select", // 选择按钮
"to_button_id": "$pressed_button_name",
"mapping_type": "pressed"
},
{
"from_button_id": "button.menu_up", // 上方向键
"to_button_id": "$pressed_button_name",
"mapping_type": "global" // 全局映射
}
]
}
}
```
### 映射类型
定义按钮映射的作用范围:
- `focused` - 控件获得焦点时生效
- `pressed` - 控件被点击/按压时生效
- `global` - 控件存在时全局生效
条件触发示例:
```json
{
"sample_button@common.button": {
"$pressed_button_name": "button_id",
"button_mappings": [
// 鼠标悬停时触发
{
"from_button_id": "button.menu_ok",
"to_button_id": "$pressed_button_name",
"mapping_type": "focused"
},
// 点击时触发
{
"from_button_id": "button.menu_select",
"to_button_id": "$pressed_button_name",
"mapping_type": "pressed"
},
// 全局响应上方向键
{
"from_button_id": "button.menu_up",
"to_button_id": "$pressed_button_name",
"mapping_type": "global"
}
]
}
}
```
### 常用按钮ID
**键鼠映射表:**
| 按钮ID | 说明 |
|-----------------------------|---------------|
| `button.menu_select` | 鼠标左键 |
| `button.menu_secondary_select` | 鼠标右键 |
| `button.menu_ok` | 回车键 |
| `button.menu_exit` | ESC键 |
| `button.menu_cancel` | ESC键 |
| `button.menu_up` | 上方向键 |
| `button.menu_down` | 下方向键 |
| `button.menu_left` | 左方向键 |
| `button.menu_right` | 右方向键 |
| `button.menu_autocomplete` | Tab键 |
**手柄映射表:**
| 按钮ID | 说明 |
|-----------------------------|-------------|
| `button.controller_select` | X/A键 |
| `button.menu_secondary_select` | Y键 |
| `button.menu_exit` | B键 |
| `button.menu_cancel` | B键 |
| `button.menu_up` | 方向键上 |
| `button.menu_down` | 方向键下 |
| `button.menu_left` | 方向键左 |
| `button.menu_right` | 方向键右 |
建议在设计UI时兼容多种输入设备。
## 修改操作
使用`modifications`属性可以非侵入式地修改现有JSON UI元素提升资源包兼容性。
| 操作类型 | 描述 |
|------------------|-----------------------|
| `insert_back` | 在数组末尾插入 |
| `insert_front` | 在数组开头插入 |
| `insert_after` | 在目标元素后插入 |
| `insert_before` | 在目标元素前插入 |
| `move_back` | 移动元素到数组末尾 |
| `move_front` | 移动元素到数组开头 |
| `move_after` | 移动元素到目标之后 |
| `move_before` | 移动元素到目标之前 |
| `swap` | 交换两个元素位置 |
| `replace` | 替换目标元素 |
| `remove` | 移除目标元素 |
### 操作示例
#### 首尾操作
```json
// 在控件列表开头插入新元素
{
"array_name": "controls",
"operation": "insert_front",
"value": [{"foo@example.bar": {}}]
}
// 将现有元素移至末尾
{
"array_name": "controls",
"operation": "move_back",
"value": [{"foo@example.bar": {}}]
}
```
#### 相对定位操作
```json
// 在指定绑定后插入新绑定
{
"array_name": "bindings",
"operation": "insert_after",
"where": {"binding_name": "#example_binding_2"},
"value": [{"binding_name": "#my_binding_1"}]
}
// 移动绑定到指定位置前
{
"array_name": "bindings",
"operation": "move_before",
"where": {"binding_name": "#example_binding_1"},
"target": {"binding_name": "#example_binding_2"}
}
```
#### 替换与删除
```json
// 替换现有绑定
{
"array_name": "bindings",
"operation": "replace",
"where": {"binding_name": "#example_binding_1"},
"value": {"binding_name": "#replacement_binding"}
}
// 删除指定绑定
{
"array_name": "bindings",
"operation": "remove",
"where": {"binding_name": "#example_binding_1"}
}
```

View File

@@ -0,0 +1,89 @@
---
title: 添加HUD元素
category: 教程
tags:
- 初学者
mentions:
- shanewolf38
- SmokeyStack
---
# 添加HUD元素
<!--@include: @/wiki/bedrock-wiki-mirror.md-->
在本教程中你将学习如何向HUD界面添加元素。
## 概述
HUD界面在游戏中大部分时间都会显示为玩家提供关键信息。很多时候你需要在界面上添加元素比如在完成特定事件后弹出文字、显示玩家体力的耐力条、显示玩家速度的时速表等等
要将创建的元素添加到HUD界面需要使用`modification`参数在`root_panel`中添加新的`control`界面元素。Root_panel是一个面板类型的元素包含了HUD界面上几乎所有显示的元素。
## 单个元素添加
下面这段代码会在屏幕顶部创建一个显示黑色方块的图像元素,在屏幕右上角创建显示文字"HUD文本"的标签元素,并通过修改`root_panel`将它们添加到HUD界面。
::: code-group
```json [RP/ui/hud_screen.json]
"hud_square": {
"type": "image",
"texture": "textures/ui/Black", // 原版纹理
"anchor_from": "top_middle",
"anchor_to": "top_middle",
"size": [ 64, 64 ],
"offset": [ 0, 4 ]
},
"hud_text": {
"type": "label",
"text": "HUD文本",
"anchor_from": "top_right",
"anchor_to": "top_right",
"offset": [ -4, 4 ]
},
"root_panel": {
"modifications": [
{
"array_name": "controls",
"operation": "insert_front",
"value": [
{ "hud_square@hud.hud_square": {} },
{ "hud_text@hud.hud_text": {} }
]
}
]
},
```
需要添加到HUD界面上的所有元素都列举在root_panel的`modifications`->`value`部分。在添加元素时使用的命名空间标识(例如`@hud.hud_square`)可以根据实际模块进行调整。比如当`hud_square`元素是创建在`scoreboard`命名空间的scoreboards.json界面文件中时添加时应使用`@scoreboard.hud_square`。
## 组合元素添加
出于组织结构考虑,通常不建议将大量元素直接逐个添加到根面板中。以下代码将之前定义的`hud_square`和`hud_text`元素(示例中未展示)包裹在名为`hud_elements_panel`的面板元素中然后将该面板整体添加到HUD的根面板。最终效果与单个元素添加方式相同。
::: code-group
```json [RP/ui/hud_screen.json]
"hud_elements_panel": {
"type": "panel",
"controls": [
{ "hud_square@hud_square": {} },
{ "hud_text@hud_text": {} }
]
},
"root_panel": {
"modifications": [
{
"array_name": "controls",
"operation": "insert_front",
"value": [
{ "hud_elements_panel@hud.hud_elements_panel": {} }
]
}
]
},
```
此处`hud_elements_panel`没有直接定义尺寸参数,因此将继承其父元素(`root_panel`的尺寸。这使得子元素的锚点定位、百分比尺寸等效果能相对于HUD屏幕进行适配。

View File

@@ -0,0 +1,64 @@
---
title: Aseprite动画
category: 教程
mentions:
- TheDataLioness
- shanewolf38
- TheItsNameless
- LeGend077
- stirante
---
# Aseprite动画
<!--@include: @/wiki/bedrock-wiki-mirror.md-->
## Aseprite简介
[Aseprite](https://www.aseprite.org/) 是一款付费像素艺术软件,专门用于轻松创建皮肤和资源包。它提供丰富的工具、详尽的文档和教程,适合不同水平的艺术家使用。
[LibreSprite](https://libresprite.github.io/) 是Aseprite的免费开源替代品。它基于Aseprite最后一个开源许可版本进行分支开发本教程中的操作同样适用于LibreSprite。
## 在Aseprite中创建动画
假设你有一组按数字1到5顺序命名的"frameimage"系列帧图像。导入第一张图像后Aseprite会自动识别同名但编号不同的其他图片将它们按正确顺序排列并创建动画。
<FolderView
:paths="[
'frameimage1.png',
'frameimage2.png',
'frameimage3.png',
'frameimage4.png',
'frameimage5.png'
]"
></FolderView>
使用`箭头键`在帧间导航,`Enter键`控制动画的播放/暂停。按下`Tab键`可打开时间轴选择单帧,右键点击时间轴上的帧可设置各种参数。
通过快捷键`Ctrl + E`或菜单`文件 -> 导出到精灵表`进行导出操作。在输出设置中选择输出文件和JSON数据格式出现包含哈希Hash和数组Array两种选项的下拉菜单时请确保选择数组Array模式否则会导致异常。
最终将生成两个文件SpriteSheet图像和JSON文件。请确保这两个文件主文件名相同且扩展名不同。
## 在JSON-UI中使用Aseprite动画
`aseprite_flip_book`动画类型专用于`image`类型元素的`uv`属性配置。
::: code-group
```json [RP/ui/example_file.json]
{
"image_element": { // 此处为动画元素
"type": "image",
"texture": "textures/ui/my_sprite_file",
"uv_size": [32, 32],
"uv": "@example_namespace.image_uv_animation"
},
"image_uv_animation": { // 此处为动画控制参数
"anim_type": "aseprite_flip_book",
"initial_uv": [0, 0]
}
}
```
:::
将`texture`字段设置为导出文件的路径(不包含扩展名)。`uv_size`字段应设置为单帧的宽高尺寸。

View File

@@ -0,0 +1,78 @@
---
title: 保留标题文本
category: 教程分类
tags:
- 中级
mentions:
- shanewolf38
- SmokeyStack
---
# 保留标题文本
<!--@include: @/wiki/bedrock-wiki-mirror.md-->
在本教程中,您将学习如何保存绑定数据并根据含有特定字符串的标题更新界面元素。
## 概述
标题是向UI系统传递数据的常用方法。当标题包含特定字符串时才更新相关数据元素而忽略所有不含该字符串的标题数据非常有用。尽管本教程以标题为例但该方法适用于所有通过绑定传递的数据如副标题、玩家记分板名称等
要保存特定字符串,我们需要组合使用 `visibility_changed` 绑定更新条件和 `source_control_name`,从而仅在包含特定字符串时更新绑定,并将该绑定传递给另一个元素。
## 标题指令
以下代码创建了一个标签元素,当将其添加到根面板时,可以在屏幕显示包含字符串"update"的标题(显示文本中会移除"update"部分)。后续传入的标题信息只有包含"update"时才会更新显示文本。
::: code-group
```json [RP/ui/hud_screen.json]
"preserved_title_display": {
"$update_string": "update", // 标题必须包含此字符串才触发元素更新
"type": "label",
"text": "#text",
"controls": [
{
"data_control": {
"type": "panel",
"size": [ 0, 0 ],
"bindings": [
{
"binding_name": "#hud_title_text_string" // 读取当前标题字符串
},
{
"binding_name": "#hud_title_text_string",
"binding_name_override": "#preserved_text", // 元素可见性变化时更新#preserved_text
"binding_condition": "visibility_changed"
},
// 当包含更新字符的标题传入后,元素会短暂可见后立即隐藏
{
"binding_type": "view",
"source_property_name": "(not (#hud_title_text_string = #preserved_text) and not ((#hud_title_text_string - $update_string) = #hud_title_text_string))",
"target_property_name": "#visible"
}
]
}
}
],
"bindings": [
{
"binding_type": "view",
"source_control_name": "data_control", // 从"data_control"子元素读取绑定
//"resolve_sibling_scope": true, // 当"data_control"与绑定调用元素为同级时需启用
"source_property_name": "(#preserved_text - $update_string)", // 从显示文本中移除更新字符串
"target_property_name": "#text"
}
]
},
```
变量 `$update_string` 定义了触发元素更新的标题必须包含的特定字符串。子元素 `data_control` 用于在标题包含更新字符串时存储标题文本。`data_control` 必须是要传递保留文本元素的子级或同级元素,因为其可见性变化会触发文本保存。该元素的三个绑定分别实现:
1. 首绑定:持续追踪当前标题文本
2. 次绑定:在元素可见性变化时将当前标题保存至 `#preserved_text`
3. 末绑定:当传入含更新字符串的标题时短暂显示元素后立即隐藏
在 `data_control` 元素的第三个绑定中,需同时满足两个条件才可见:
1. `not (#hud_title_text_string = #preserved_text)` - 当前标题与保存标题不一致时成立
2. `not ((#hud_title_text_string - $update_string)` - 当前标题含有更新字符串时成立
当含有更新字符串且与已存文本不同的标题传入时,两条件同时触发,元素更新数据后立即重新隐藏自身。

View File

@@ -0,0 +1,80 @@
---
title: 字符串转数值
category: 教程
tags:
- 中级
mentions:
- shanewolf38
- SmokeyStack
- ThomasOrs
---
# 字符串转数值
<!--@include: @/wiki/bedrock-wiki-mirror.md-->
在本教程中,您将学习如何将数字字符串转换为数值,以及如何将数值转换为文本字符串。
## 概述
在许多情况下会有文本字符串通过标题、操作栏、记分板或其他来源传递到用户界面中。当我们希望根据输入的字符串动态调整UI元素时能够进行数字比较就显得非常重要。但类似于"34"或"89"这样的数值型字符串通常会被视为普通文本,既无法与数值进行比较,也难以直接作为运算数据使用。此时我们需要将这类字符串转换为数值。
要实现字符串到数值的转换,我们可以利用乘法运算特性。任何包含数字的字符串与数值相乘,或者通过去除字符串中的非数字部分,都能使游戏引擎将该值作为数值而非字符串处理。
## 字符串转数值
以下代码创建了一个标签元素当添加到主面板时可在记分板侧栏的最高分值处于100-999范围内时显示该数值。
::: code-group
```json [RP/ui/hud_screen.json]
"string_to_number": {
"type": "label",
"text": "#player_score_sidebar",
"bindings": [
{
"binding_name": "#player_score_sidebar",
"binding_type": "collection",
"binding_collection_name": "scoreboard_scores"
},
{
"binding_type": "view",
"source_property_name": "(#player_score_sidebar * 1)", // 将分数从字符串转换为数值
"target_property_name": "#score"
},
{
"binding_type": "view",
"source_property_name": "((#score > 99) and (#score < 1000))", // 仅在100-999范围内可见
"target_property_name": "#visible"
}
]
}
```
第一个绑定从记分板侧栏读取最大数值该绑定值以字符串形式固定传输第二个绑定通过将分数乘以1将其转换为数值也可以通过减法操作去除字符串中的文本第三个绑定设置元素仅在分数大于99且小于1000时可见。
**注意:** 如果需要将数值识别为浮点类型而非整数可在等式运算中引入浮点变量或绑定例如除以1.0(必须通过变量或绑定实现——直接插入浮点数无法生效)。这在处理`#clip-ratio`绑定时尤为实用。
## 数值转字符串
以下代码创建了一个标签元素,当添加到主面板时,可将"Strength: #"格式标题中的数字部分单独显示。
::: code-group
```json [RP/ui/hud_screen.json]
"number_to_string": {
"type": "label",
"text": "#text",
"bindings": [
{
"binding_type": "global",
"binding_name": "#hud_title_text_string"
},
{
"binding_type": "view",
"source_property_name": "('§z' + (#hud_title_text_string - 'strength: '))",
"target_property_name": "#text"
}
]
}
```
当使用标题、副标题等方式传递包含数字的文本时,此方法可单独显示数值。通过减法运算去除多余文本后,需在数值前添加文本使其转换为字符串类型(`text`参数无法直接读取纯数值型绑定)。此例中的括号并非必需,主要用于区分数值转换操作。添加的`§z`字符是无效的Minecraft格式代码既不显示也不影响标签颜色参数。若需要去除显示中无法通过减法处理的文本推荐将元素嵌套在设置`"clips_children": true`和适当尺寸的容器面板中实现遮挡效果。

File diff suppressed because it is too large Load Diff