将 spritesheet 中的精灵存储在数组 Libgdx 中

Posted

技术标签:

【中文标题】将 spritesheet 中的精灵存储在数组 Libgdx 中【英文标题】:Store sprites from spritesheet in array Libgdx 【发布时间】:2016-07-06 18:58:27 【问题描述】:

我将 960x960 的 spritesheet 作为 png 存储在我的 Libgdx android 资产中。在我指定初始化用于我的游戏的精灵的类中,我试图让它从精灵表中切割出一个 120x120 的精灵(因此数组中应该有 64 个项目)。我怎么能做到这一点?这是我在类似情况下尝试过的:

public static Texture spritesheet;
public static Sprite[] textures = new Sprite[64];
...
    //inside method that gets called once to initialize variables
    spritesheet = new Texture(
            Gdx.app.getType() == Application.ApplicationType.Android ?
                    "...Spritesheet.png" :
                    "android/assets/...Spritesheet.png"
    );
    spritesheet.setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear);

    for (int x = 0; x < 64; x ++) 
        textures[x] = new Sprite(spritesheet, x, (x%8), 64, 64);
        textures[x].flip(false, true);
    

然后我用这个在其他类中渲染精灵:

batch.draw(Assets.textures[0 /*this can be any number*/], (float) x, (float) y, 108, 108);

当我这样做时,它的行为真的很奇怪。它说数组中填充了元素,但仍然存在数组索引超出范围异常或精灵只是疯狂渲染。总的来说,它没有成功。我想要做的是让它,这样我就不必分别初始化 64 个不同的精灵,然后我可以通过更改渲染精灵时输入的索引来轻松更改精灵,这样我以后可以做一些其他的事情开,像动画一样。我该怎么做?

【问题讨论】:

【参考方案1】:

您应该为此使用 TextureAtlas。地图集是由 LibGDX TexturePacker 从单独的图像自动生成的文件。它存储从工作表中的图像边界到NinePatch 信息的所有内容。您需要做的就是将单独的图像放在一个文件夹中,然后在该文件夹上运行 TexturePacker。这将为您创建一个可以轻松加载的工作表和 .atlas/.pack 文件。

如果您在使用命令行时遇到困难,可以使用 TexturePackerGui,但我建议您使用命令行,甚至在您的应用程序中使用它。

我通常会在开发时动态创建这些表格。我可以轻松覆盖单独的图像,并且在我再次运行我的应用程序后它们会立即生效。我首先在项目的根目录下创建一个新文件夹images。然后对于我需要的每个包,我创建另一个文件夹。对于此示例,我在 images 中创建文件夹 tileset。在DesktopLauncher 中,我将设置此文件夹以从图像中生成图集。

    TexturePacker.Settings settings = new TexturePacker.Settings();
    settings.maxWidth = 1024;
    settings.maxHeight = 1024;

设置文件指定有关您的图集的所有内容。单张纸的最大尺寸,如果它应该从图像、填充、旋转等中去除透明度。它们都非常简单,您可以在文档中查看所有这些。使用这些设置,您可以创建您的图集。

    TexturePacker.process(settings, 
            "../../images/tileset", //where to find the images to be packed.
            "../../android/assets/tileset/", //where to store the atlas and sheet
            "tileset"); //what filename to use

现在您可以打开 .atlas 文件,您会看到它使用文件名作为别名。此别名用于查找它们,但我们先加载图集。

TextureAtlas atlas = new TextureAtlas("tileset/tileset.atlas");

通过只将一个字符串传递给构造函数,它默认在您的本地路径中查找,而本地路径又默认在android/assets/ 中。现在我们可以要求图集交出我们在工作表中的资产。

atlas.findRegion("别名"); //交出名为“alias”的工作表上的图像

查找这样的纹理有点昂贵。您不想每次更新都查找很多这样的纹理,因此您仍然需要将它们存储在某个地方。

如果您将图像序列命名为 image_01.pngimage_02.pngimage_03.png,它将以相同的名称存储它们,并在图集中对它们进行排序,但它是 index。因此,如果您想要一个单独的某些纹理数组,您可以使用 _xx 命名它们并一次性获取它们:

atlas.findRegions("alias");

这对于Animation 来说特别方便。只需将您的图像序列复制到一个文件夹并指定它进行打包。正确命名您的序列并将区域分配给动画。一切都会立即生效。

使用AssetManager 加载TextureAtlas 与普通Texture 几乎相同,除非您指定它来自TextureAtlas.class。您总是会加载 .atlas,而后者又会处理您的图像。

我总是使用AssetDescriptor 来加载我的资产。如果我在你所在的地方,我会摆脱静态的 Assets.textures[] since that will get you into trouble sooner or later。

//None static AssetManager with getter
private AssetManager manager = new AssetManager();
public AssetManager getManager()  return manager; 

//Specify a descriptor for the atlas, this is static so I can acces it anywhere. 
//It's just a descriptor of the asset so this is safe.
public static final AssetDescriptor<TextureAtlas> TileSet = new AssetDescriptor<TextureAtlas>("tileset/tileset.atlas", TextureAtlas.class);

//then just load everything
public void load()

    manager.load(tileSet);
    //... load other stuff

现在只需将AssetManager 对象传递到您需要访问资产的任何地方,您就可以像这样加载任何资产:

TextureAtlas tileset = assetManager.get(Assets.TileSet);

【讨论】:

纹理图集是缩放的好主意,但了解它的工作原理仍然很重要。竖起大拇指。【参考方案2】:

我认为你的 for 循环应该是这样的

for(int x = 0; x < 64; x ++)
    textures[x] = new Sprite(
        spritesheet, 
        (x%8)*64, //where x=3, (3%8)*64 = 3*64 = 192px sourceX
        (x/8)*64, //where x=3, (int)(3/8)*64 = 0*64 = 0px sourceY
        64, //source width
        64 //source height
    );


Another test case where x=20;
(20%8)*64 = 4*64 = 256px SourceX
(20/8)*64 = 2*64 = 128px SourceY

【讨论】:

以上是关于将 spritesheet 中的精灵存储在数组 Libgdx 中的主要内容,如果未能解决你的问题,请参考以下文章

任何 spritesheet 的可调用 spritesheet 类

Spritesheet 以编程方式切割:最佳实践

多个精灵表中的 Unity 9-slice

使用 XNA/Monogame 从 spritesheet 中绘制一个 sprite

Windows Phone 应用程序中的 SpriteSheet 动画

SVG 和精灵表