我将960x960 spritesheet存储为我的Libgdx android资产中的png。在我已经指定用于初始化精灵以用于我的游戏的类中,我试图使它从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);
}
然后我用其他的类渲染精灵:
batch.draw(Assets.textures[0 /*this can be any number*/], (float) x, (float) y, 108, 108);
当我这样做时,它的行为非常奇怪。它说数组中已经填充了元素,但是仍有数组索引超出界限,或精灵只是疯狂渲染。总的来说,它还没有成功。我想要做的就是这样做,所以我不必分别初始化64个不同的精灵,并且这样做我可以通过改变渲染精灵时输入的索引来轻松改变精灵,这样我就能做到稍后会有其他一些事情,比如动画。我怎么能这样做呢?
答案 0 :(得分:4)
您应该使用TextureAtlas来实现此目的。地图集是由LibGDX TexturePacker从单独的图像自动生成的文件。它存储从工作表中的图像边界到NinePatch
信息的所有内容。您需要做的就是将单独的图像放在一个文件夹中,然后在该文件夹上运行TexturePacker。这将为您创建一个可以轻松加载的工作表和.atlas / .pack文件。
如果您对命令行有困难,则存在TexturePackerGui,但我建议使用命令行,甚至在您的应用中使用它。
我通常做的是在我开发时动态创建这些工作表。我可以轻松覆盖单独的图像,并在我再次运行我的应用程序后立即生效。我首先在项目的根目录下创建一个新文件夹images
。然后对于每个包我需要创建另一个文件夹。对于此示例,我在tileset
中创建了文件夹images
。在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(&#34;别名&#34); //移交名为&#34;别名&#34;
的工作表上的图像查找这样的纹理有点贵。你不想在每次更新时查找这样的许多纹理,所以你仍然需要将它们存储在某个地方。
如果您将图片序列命名为image_01.png
,image_02.png
,image_03.png
,则会将它们全部存储在同一名称下,并在图册中对它们进行排序。index
_xx
1}}。因此,如果您想要一个单独的某些纹理数组,您可以使用atlas.findRegions("alias");
命名它们并一次性获取它们:
Animation
这对TextureAtlas
尤其方便。只需将图像序列复制到文件夹并指定要打包即可。正确命名序列并将区域赋予动画。一切都将立即起作用。
使用AssetManager
加载Texture
与普通TextureAtlas.class
几乎相同,除非您从.atlas
指定它。您始终会加载AssetDescriptor
,而后者会处理您的图片。
我总是使用Assets.textures[]
来加载我的资源。如果我在哪里,我将摆脱静态//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
}
since that will get you into trouble sooner or later。
AssetManager
现在只需将TextureAtlas tileset = assetManager.get(Assets.TileSet);
对象传递到您需要访问资产的任何位置,您就可以加载任何资产:
symbolColor
答案 1 :(得分:0)
我认为你的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