在spgesheet中存储sprite,数组为Libgdx

时间:2016-03-20 07:20:05

标签: java android arrays libgdx sprite-sheet

我将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个不同的精灵,并且这样做我可以通过改变渲染精灵时输入的索引来轻松改变精灵,这样我就能做到稍后会有其他一些事情,比如动画。我怎么能这样做呢?

2 个答案:

答案 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.pngimage_02.pngimage_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