☰

生成和加载 UI 精灵表

简介

精灵(Sprite)是二维图像,主要用于游戏的用户界面中。精灵表(Sprite Sheet)是此类图像的集合。换句话说,精灵被打包在一起形成一张精灵表。本文档将介绍以下步骤:

前提条件

添加精灵

生成精灵表

为了生成精灵表,运行位于 INSTALLATION_PATH\Mount & Blade II Bannerlord\bin\Win64_Shipping_wEditor 的 TaleWorlds.TwoDimension.SpriteSheetGenerator.exe 可执行文件。如果你已按照上述步骤操作,在运行 SpriteSheetGenerator.exe 后,你应该会看到以下窗口:

SpriteSheetGenerator.exe 将在 Modules\YOUR_MODULE_NAME 下创建两个名为 Assets 和 AssetSources 的文件夹。它还会在 Modules\YOUR_MODULE_NAME\GUI 下创建一个 SpriteData.xml 文件(带有你的模组名称前缀)。

导入已创建的精灵表

为了使用你精灵表中的精灵,你还需要从资源浏览器(resource browser)中导入它们。请注意,如果你只是为启动器添加精灵,则应跳过此步骤。

按照以下步骤导入精灵表:

这应该会打开资源浏览器:

折叠资源浏览器左侧名为 Native 的文件夹,以便更轻松地找到你的模组。然后,选择你的模组。

打开你模组中的 GauntletUI 文件夹。然后,按下下面用红色箭头标出的”Scan new asset files”(扫描新资源文件)按钮(右侧箭头)。

这应该会打开一个新窗口:

确保选中了你的分类(在本示例中为 ui_mycategory),然后点击 Import(导入)按钮。然后,你应该会看到类似这样的内容:

关闭资源浏览器和游戏。 你现在应该会在 Modules\YOUR_MODULENAME\Assets\GauntletUI 下看到一个名为 ui{YOUR_CATEGORY_NAME}_1_tex.tpac 的新文件。

在 UI XML 文件中使用精灵

你现在可以使用你创建的精灵表中的精灵了(你还需要加载相应的分类,这在下面的加载与卸载精灵分类部分中有说明)。精灵在 UI XML 文件中使用。你可以通过名称来引用你的精灵。你可以在位于 Modules\YOUR_MODULE_NAME\GUI 的 SpriteData.xml 文件(带有你的模组名称前缀)中找到你精灵的名称。 举个例子,我们将创建一个新的 UI XML 文件。为此,返回到 Modules\YOUR_MODULE_NAME\ 下名为 GUI 的文件夹,并创建一个名为 Prefabs 的新文件夹。在 Prefabs 文件夹下创建一个名为 MyXml.xml 的新文件。你现在可以在这个文件中通过 Sprite=“mysprite” 来引用你的精灵。例如,MyXml.xml 文件的内容可以是:

<Prefab>
    <Window>
        <Widget DoNotAcceptEvents="true" DoNotPassEventsToChildren="true" WidthSizePolicy="StretchToParent" HeightSizePolicy="StretchToParent">
            <Children>
                <ImageWidget WidthSizePolicy="Fixed" HeightSizePolicy="Fixed" SuggestedWidth="128" SuggestedHeight="128" HorizontalAlignment="Center" VerticalAlignment="Center" Sprite="mysprite"/>
            </Children>
        </Widget>
    </Window>
</Prefab>

加载与卸载精灵分类

为了使用你添加的精灵,你需要加载它们。在这方面,你有两种选择:¸

  1. 手动加载与卸载

    • 开发者拥有更多的控制权。他们可以选择何时加载和卸载精灵分类。因此,他们可以管理内存使用和性能。
    • 需要编写代码。因此,比 AlwaysLoad 选项更复杂。
  2. 使用 AlwaysLoad 选项

    • 精灵分类在启动时自动加载。
    • 分类会保留在内存中,直到游戏关闭。因此,每次使用时无需手动加载它们。
    • 以增加内存使用为代价,减少 UI 加载时间。
    • 易于使用。
1. 手动加载与卸载

这里我们展示如何手动加载和卸载精灵分类。在下面的示例中,我们重写了 MBSubModuleBase 类的 OnGameStart 和 OnGameEnd 方法,分别用于添加和移除 MyScreen 全局层(global layer)。请注意,MyScreen 的构造函数加载了我们在前面章节中创建的精灵分类和 UI XML。我们还在 OnFinalize 方法中卸载了该精灵分类。

如果你要复制下面的代码,别忘了更改命名空间(namespace)和 Main 函数的名称。它们应该与你 SubModule.xml 中的字段相匹配。换句话说,你应该在 SubModule.xml 的这个字段中,将 SpritesheetDocumentation(命名空间)更改为 YOUR_MODULE_NAME,将 Main(Main 函数的名称)更改为 YOUR_MAIN_FUNCTION_NAME:

<SubModuleClassType value="YOUR_MODULE_NAME.YOUR_MAIN_FUNCTION_NAME"/>

否则,它们将无法被识别,游戏将在启动时崩溃。

using TaleWorlds.Core;
using TaleWorlds.MountAndBlade;
using TaleWorlds.Engine.Screens;
using TaleWorlds.Engine.GauntletUI;
using TaleWorlds.GauntletUI.Data;
using TaleWorlds.TwoDimension;

namespace SpritesheetDocumentation
{
    public class Main : MBSubModuleBase
    {
        private MyScreen _myScreen;

        protected override void OnSubModuleLoad()
        {

        }

        protected override void OnGameStart(Game game, IGameStarter gameStarterObject)
        {
            base.OnGameStart(game, gameStarterObject);
            _myScreen = new MyScreen();
            ScreenManager.AddGlobalLayer(_myScreen, true); // add MyScreen on game start
        }

        public override void OnGameEnd(Game game)
        {
            base.OnGameEnd(game);
            _myScreen.OnFinalize();
            ScreenManager.RemoveGlobalLayer(_myScreen); // remove MyScreen on game end
        }
    }

    public class MyScreen : GlobalLayer
    {
        private GauntletLayer _gauntletLayer;
        private IGauntletMovie _gauntletMovie;
        private SpriteCategory _category;

        public MyScreen()
        {
            var spriteData = UIResourceManager.SpriteData;
            var resourceContext = UIResourceManager.ResourceContext;
            var resourceDepot = UIResourceManager.UIResourceDepot;

            _category = spriteData.SpriteCategories["ui_mycategory"]; // select which category to load, put your category name here
            _category.Load(resourceContext, resourceDepot); // load the selected category

            _gauntletLayer = new GauntletLayer(2);
            Layer = (ScreenLayer)_gauntletLayer;

            _gauntletMovie = _gauntletLayer.LoadMovie("MyXml", null); // load the ui xml in Prefabs folder
        }

        public void OnFinalize()
        {
            // unload ui xml, sprite category, layer, etc.
            _gauntletMovie = null;
            _category.Unload();
            _gauntletLayer = null;
        }
    }
}
2. 使用 AlwaysLoad 选项

与手动加载与卸载部分中手动加载精灵分类不同,你可以通过为特定分类启用 AlwaysLoad 选项,来选择哪些精灵分类应在启动时自动加载。除非开发者手动卸载,否则启用了 AlwaysLoad 选项的分类将一直保留在内存中,直到游戏关闭,这样你就不必每次使用时都手动加载它们。启用 AlwaysLoad 选项会减少 UI 的加载时间(因为这些分类只在启动时加载一次),但会增加内存使用(因为即使这些分类未被使用,也会保留在内存中)。此选项对于经常被加载和卸载的分类非常有用(例如,用于一个频繁打开和关闭的屏幕的分类)。

注意:此功能随 e1.6.2 版本发布。如果你使用的是更早的版本,但仍想使用 AlwaysLoad 选项,请将游戏和模组开发工具包(modding kit)都切换到 e1.6.2 或更新的版本。

要为某个分类启用 AlwaysLoad 选项,请按照以下步骤操作:

在文件夹 Modules\YOUR_MODULE_NAME\GUI\SpriteParts 下创建一个名为 Config.xml 的新 XML 文件。将以下内容复制并粘贴到 Config.xml 中:

<Config>
    <SpriteCategory Name="ui_{YOUR_CATEGORY_NAME}">
        <AlwaysLoad/>
    </SpriteCategory>
</Config>

将 ui_{YOUR_CATEGORY_NAME} 替换为你的分类。然后,按照上面生成精灵表部分中的步骤生成精灵表。要检查一切是否正常,请打开位于 Modules\YOUR_MODULE_NAME\GUI 的 {YOUR_MODULE_NAME}SpriteData.xml 文件。在那里你应该会看到,你在 Config.xml 中选择的分类已启用了 AlwaysLoad 选项:

<SpriteData>
    <SpriteCategories>
        <SpriteCategory>
            <Name>ui_{YOUR_CATEGORY_NAME}</Name>
            <AlwaysLoad />
            <SpriteSheetCount>1</SpriteSheetCount>
            <SpriteSheetSize ID="1" Width="512" Height="512" />
        </SpriteCategory>
    </SpriteCategories>
    ...
</SpriteData>

你不需要更改/添加任何代码来加载新的精灵表分类。

结论

为了看到下面的结果,请确保你已经创建了一个屏幕,并加载了你在”在 UI XML 文件中使用精灵”部分创建的 UI XML 文件。

注意:如果你已经使用 AlwaysLoad 选项添加了你的精灵分类,但没有使用”手动加载与卸载”部分中分享的代码,你可以编写自己的代码来创建一个屏幕并加载 UI XML。如果你不知道该怎么做,可以复制”手动加载与卸载”部分中的代码(也请阅读该部分中的详细信息),并删除以下几行,因为你已经使用了 AlwaysLoad 选项,不需要手动加载该分类:

var spriteData = UIResourceManager.SpriteData;
var resourceContext = UIResourceManager.ResourceContext;
var resourceDepot = UIResourceManager.UIResourceDepot;

_category = spriteData.SpriteCategories["ui_mycategory"]; // select which category to load, put your category name here
_category.Load(resourceContext, resourceDepot); // load the selected category

你也可以删除 _category 字段并移除对它的引用。

本页面由 AI 翻译,可能存在不准确之处。请以英文原版为准。