XML 使用说明 - 定义绘制结构树

在游戏配置文件中,您可以使用 <DrawNodeDef> 元素来定义复杂的绘制结构树。每个 <DrawNodeDef> 元素都必须包含在顶层的 <Define> 元素之内,并遵循其通用的属性定义规则。

功能介绍

<DrawNodeDef> 用于构建游戏对象的视觉表现结构,可以组合多个纹理和子节点来形成复杂的身体结构、动画序列或可动部件。它支持纹理引用、节点定位和动画帧率设置。

参数说明

绝大多数参数都必须通过嵌套元素的方式进行赋值。nodeNamepositionFPS 允许在属性栏定义,这是为了方便紧凑的结构定义。

  • <defName> (必需,字符串)

    • 该绘制结构定义的唯一标识符。在整个游戏配置中,此名称必须是全局唯一的,除非您有意覆盖现有定义。
    • 作为匿名定义时,此字段可以省略。
  • <label> (可选,字符串)

    • 提供一个人类可读的标签,用于更好地理解该绘制结构定义的用途。
  • <description> (可选,字符串)

    • 提供更详细的文本描述,解释该绘制结构定义的具体内容或特殊用途。
  • <textures> (可选,字符串数组)

    • 一个字符串数组,包含对 ImageDef 的引用。这些引用可以是完整的 ImageDefdefName,也可以是其子图的 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> 数组中,您可以使用 ImageDefdefName 来引用完整的图片,或者使用 defName_编号 来引用图片切分后的特定子图。

  • 引用 DrawNodeDef<nodes> 数组中,您可以引用其他已定义的 <DrawNodeDef>,或者进行匿名定义。

    • 引用已命名定义: 直接在 <li> 元素中放置被引用 DrawNodeDefdefName
    • 匿名定义: 直接在 <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:定义一个具有动画的腿部,并作为另一个绘制节点的子节点

假设我们有一个 LegAnimationImageImageDef,它被切分成了多个子图(例如 LegAnimationImage_0LegAnimationImage_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 的子类,不支持元素定义方式。