XML 使用说明 - 定义绘制结构树
在游戏配置文件中,您可以使用 <DrawNodeDef> 元素来定义复杂的绘制结构树。每个 <DrawNodeDef> 元素都必须包含在顶层的 <Define> 元素之内,并遵循其通用的属性定义规则。
功能介绍
<DrawNodeDef> 用于构建游戏对象的视觉表现结构,可以组合多个纹理和子节点来形成复杂的身体结构、动画序列或可动部件。它支持纹理引用、节点定位和动画帧率设置。
参数说明
绝大多数参数都必须通过嵌套元素的方式进行赋值。nodeName、position 和 FPS 允许在属性栏定义,这是为了方便紧凑的结构定义。
-
<defName>(必需,字符串)- 该绘制结构定义的唯一标识符。在整个游戏配置中,此名称必须是全局唯一的,除非您有意覆盖现有定义。
- 作为匿名定义时,此字段可以省略。
-
<label>(可选,字符串)- 提供一个人类可读的标签,用于更好地理解该绘制结构定义的用途。
-
<description>(可选,字符串)- 提供更详细的文本描述,解释该绘制结构定义的具体内容或特殊用途。
-
<textures>(可选,字符串数组)- 一个字符串数组,包含对
ImageDef的引用。这些引用可以是完整的ImageDef的defName,也可以是其子图的defName_编号。 - 数组的定义方式为
<textures><li>元素1</li><li>元素2</li></textures>。<li>元素本身会被忽略。
- 一个字符串数组,包含对
-
<nodes>(可选,绘制节点数组)- 一个
DrawNodeDef数组,包含当前绘制结构树的子节点。每个子节点本身也是一个<DrawNodeDef>,可以进一步定义其自身的纹理、位置和子节点。 - 数组的定义方式为
<nodes><li>元素1</li><li>元素2</li></nodes>。<li>元素本身会被忽略。
- 一个
-
nodeName(属性,字符串)- 定义当前绘制节点的名称。此名称可用于在代码中标识或操作特定的绘制节点。允许在属性栏定义。
-
position(属性,Vector2类型,默认为(0, 0))- 定义当前绘制节点相对于其父节点的位置偏移。此参数只能在属性栏定义。
- 定义语法:
- 位置值必须用括号
()、方括号[]或不带包裹符号的形式表示。 - 两个坐标之间可以用空格
、逗号,或分号;分隔。
- 位置值必须用括号
- 例如:
position="[1.5, -2]",position="(5; 10)",position="3 4.5"。
-
FPS(属性,浮点数,默认为5f)- 当
textures数组中包含多个纹理时,此参数定义纹理之间切换的帧率(每秒帧数),用于创建动画。允许在属性栏定义。
- 当
引用方式和匿名定义
-
引用
ImageDef: 在<textures>数组中,您可以使用ImageDef的defName来引用完整的图片,或者使用defName_编号来引用图片切分后的特定子图。 -
引用
DrawNodeDef: 在<nodes>数组中,您可以引用其他已定义的<DrawNodeDef>,或者进行匿名定义。- 引用已命名定义: 直接在
<li>元素中放置被引用DrawNodeDef的defName。 - 匿名定义: 直接在
<li>元素中定义子DrawNodeDef的所有属性和子元素。<li>元素同时作为类型说明符和匿名定义的载体。
- 引用已命名定义: 直接在
示例
示例 1:定义一个静态的身体区域(头部),包含单个纹理
<Define>
<DrawNodeDef defName="HumanoidHead" nodeName="Head" position="[0, 1.5]">
<label>人形生物头部</label>
<description>定义了人形生物的头部结构,包含其纹理。</description>
<textures>
<li>HeadTexture</li> <!-- 假设 HeadTexture 是一个已定义的 ImageDef -->
</textures>
</DrawNodeDef>
</Define>
示例 2:定义一个具有动画的腿部,并作为另一个绘制节点的子节点
假设我们有一个 LegAnimationImage 的 ImageDef,它被切分成了多个子图(例如 LegAnimationImage_0、LegAnimationImage_1 等)。
<Define>
<DrawNodeDef defName="HumanoidLeg" nodeName="LeftLeg" position="[-0.5, -1]" FPS="8.0">
<label>人形生物左腿</label>
<description>定义了人形生物的左腿,包含一个简单的行走动画。</description>
<textures>
<li>LegAnimationImage_0</li>
<li>LegAnimationImage_1</li>
<li>LegAnimationImage_2</li>
<!-- ...更多动画帧... -->
</textures>
</DrawNodeDef>
<DrawNodeDef defName="HumanoidBody" nodeName="Body" position="[0, 0]">
<label>人形生物身体</label>
<description>定义了人形生物的身体部分。</description>
<textures>
<li>BodyTexture</li>
</textures>
<nodes>
<li>HumanoidLeg</li> <!-- 引用已定义的 HumanoidLeg -->
<li> <!-- 匿名定义右腿:直接在 <li> 标签中定义其属性和子元素 -->
<textures>
<li>LegAnimationImage_0</li>
<li>LegAnimationImage_1</li>
<li>LegAnimationImage_2</li>
</textures>
<nodeName>RightLeg</nodeName>
<position>[0.5, -1]</position>
<FPS>8.0</FPS>
</li>
</nodes>
</DrawNodeDef>
</Define>
示例 3:复杂的嵌套绘制结构 (已修正匿名定义格式)
<Define>
<DrawNodeDef defName="PlayerCharacter" nodeName="Root" position="[0,0]">
<label>玩家角色绘制</label>
<description>定义了玩家角色的完整绘制结构。</description>
<textures>
<li>BasePelvisTexture</li>
</textures>
<nodes>
<li>HumanoidHead</li> <!-- 引用示例1中的头部 -->
<li>HumanoidBody</li> <!-- 引用示例2中的身体 -->
<li> <!-- 匿名定义一个武器节点 -->
<nodeName>WeaponHand</nodeName>
<position>[0.8, -0.2]</position>
<textures>
<li>SwordTexture</li>
</textures>
<nodes>
<li> <!-- 匿名定义武器尖端节点 -->
<nodeName>WeaponTip</nodeName>
<position>[0.5, 0]</position>
<!-- 只有位置,没有纹理 -->
</li>
</nodes>
</li>
</nodes>
</DrawNodeDef>
</Define>
复杂参数:position 属性定义
position 参数是一个 Vector2 类型,它只能通过属性的方式在 DrawNodeDef 标签中进行定义。其语法具有一定的灵活性。
语法规则:
- 包裹符号: 可以使用
()(括号)、[](方括号) 包裹 x 和 y 坐标,或者完全不使用包裹符号。 - 分隔符: x 和 y 坐标之间可以使用空格
、逗号,或分号;进行分隔。
常见示例:
- 无包裹,空格分隔:
position="1.5 -2.0" - 无包裹,逗号分隔:
position="1.5,-2.0" - 无包裹,分号分隔:
position="1.5;-2.0" - 括号包裹,逗号分隔:
position="(1.5, -2.0)" - 方括号包裹,分号分隔:
position="[1.5; -2.0]" - 整数值:
position="10 5" - 浮点数:
position="0.5 0.5"
注意事项:
当定义 position 时,请确保只在 DrawNodeDef 标签的属性部分进行定义,或者在数组中进行匿名定义时,作为 <li> 元素的属性进行定义。不要尝试通过 <position> 元素来定义,因为 Vector2 不是 Define 的子类,不支持元素定义方式。