java - 将 Sprite 表中的 Sprite 存储在数组 Libgdx 中

标签 java android arrays libgdx sprite-sheet

我将 960x960 spritesheet 作为 png 存储在我的 Libgdx android Assets 中。在我指定用于初始化用于我的游戏的 sprite 的类中,我试图使它从 spritesheet 中切割出一个 120x120 的 sprite(因此数组中应该有 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);
    }

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

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

当我这样做时,它的行为真的很奇怪。它说数组中填充了元素,但仍然存在数组索引越界异常或 Sprite 只是疯狂渲染。总的来说,这是行不通的。我想做的是做到这一点,这样我就不必分别初始化 64 个不同的 Sprite ,并且做到这一点,这样我就可以通过更改渲染 Sprite 时输入的索引来轻松更改 Sprite ,这样我以后就可以做一些其他的事情上,像动画。我该怎么做呢?

最佳答案

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

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

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

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

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

    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 交出我们在 sheet 中的 Assets 。

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

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

如果您将图像序列命名为 image_01.pngimage_02.pngimage_03.png,它会将它们全部存储在同一个名称下在 map 集中,它根据 index 对它们进行排序。所以如果你想要一个单独的特定纹理数组,你可以用 _xx 命名它们并一次性获得它们:

atlas.findRegions("alias");

这对于 Animation 尤其方便。只需将您的图像序列复制到一个文件夹并指定要打包即可。正确命名您的序列并将区域指定给动画。一切都会马上开始。

使用 AssetManager 加载 TextureAtlas 与普通的 Texture 几乎相同,只是您需要指定它来自 TextureAtlas .类。您始终会加载 .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 对象传递到您需要访问 Assets 的任何地方,您就可以像这样加载任何 Assets :

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

关于java - 将 Sprite 表中的 Sprite 存储在数组 Libgdx 中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36111196/

相关文章:

java - 如何找到 http 请求的 IP 地址或位置?

java - 阻止 Jsoup 获取 Http 响应

c# - 在 C# 中为 android 制作应用程序?

android - 我无法连接到 Firebase,因为 bintray-release 插件不支持 Gradle

javascript - JS循环通过AJAX-response数组填充数组,如何获取数据?

java - ElasticSearch 从多个位置获取具有一个值的数据

java - 检测Android App收到扫描请求时是否发送BLE扫描响应

python - 我如何列一个 list

python - 如何在python中随机采样矩阵?

java - 使用 setScale() 方法舍入 BigDecimal : unexpected result