【问题标题】:Store sprites from spritesheet in array Libgdx将 spritesheet 中的精灵存储在数组 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 个不同的精灵,然后我可以通过更改渲染精灵时输入的索引来轻松更改精灵,这样我以后可以做一些其他的事情开,像动画一样。我该怎么做?

【问题讨论】:

    标签: java android arrays libgdx sprite-sheet


    【解决方案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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-05-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-02
      • 2015-04-02
      • 1970-01-01
      相关资源
      最近更新 更多