我将 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.png
、image_02.png
、image_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/