1

To render crisp graphics with sprites, I decided to provide a dedicated sprite folder for every resolution size. I have 55 such folders, each folder contains 57 .png files (which means the total number is 57*55 = 3135 files). I put all 55 folders into a single folder, and run Texture Packer on that folder. In the output folder, I get 1 pack.atlas files and 212 packX.png files (X runs from 1 to 212)

in my code, I create these fields in my Assets class

private static TextureAtlas atlas;
private static Sprite logo;
// ... total of 57 Sprite fields....

And in the initialize method of the Assets class, which is called at the beginning of the game:

atlas = new TextureAtlas(Gdx.files.internal("pack.atlas"));
logo = atlas.createSprite(getWidthPath() + "logo");   //getWidthPath() returns the appropriate folder path based on the resolution size. As stated above, there are 55 such folder
//...atlas.createSprite 57 times for 57 fields....

I have done this for a smaller number of folder (3 folder) and the game runs well. However, when I decided to support all 55 resolution folders, the game cannot load on Android and can load on Desktop but really slow at the beginning.

So is it true that the large number of Sprites referenced by the pack.atlas files caused the hang?

I think if I just run TexturePacker on each resolution folder, I will get 55 pack.atlas files (instead of 1) and each pack.atlas file will now reference to 57 sprites (instead of 3135 files), the game should run fine, but it's too laborious

Hải Phong
  • 5,094
  • 6
  • 31
  • 49

2 Answers2

2

As @noone said, packing all sprites of different resolution sizes into one TextureAtlas destroys the meaning of an atlas. I mustpack one atlas for each resolution. But the problem is how to do it automatically?

After seeing that TexturePacker settings does not allow this, finally I have to modify the source code of class TexturePacker a little bit and build my own custom Libgdx build from the instruction here

I only change the main function to accept one more parameter (true or false) to specify whether or not you should pack into subfolders of the input folder. It's not a conventional way to specify options but it's enough for my case.

here is the modified main function in class TexturePacker.java

static public void main (String[] args) throws Exception {
    String input = null, output = null, packFileName = "pack.atlas";
    boolean optionSeparateFolder = false;

    switch (args.length) {
    case 4:
        packFileName = args[3];
    case 3:
        optionSeparateFolder = Boolean.parseBoolean(args[2]);
    case 2:
        output = args[1];
    case 1:
        input = args[0];
        break;
    default:
        System.out.println("Usage: inputDir [outputDir] [packToSeparateFolder] [packFileName]");
        System.exit(0);
    }
    File inputFile = new File(input);
    if (!optionSeparateFolder) {
        if (output == null) {
            output = new File(inputFile.getParentFile(), inputFile.getName() + "-packed").getAbsolutePath();
        }
        process(input, output, packFileName);
    }
    else{
        String[] childrenOfInput = inputFile.list();
        File outputFile = new File(output);
        for (int i=0; i<childrenOfInput.length; i++){
            process(inputFile.getAbsolutePath()+"/"+childrenOfInput[i],outputFile.getAbsolutePath()+"/"+childrenOfInput[i],packFileName);
        }
    }

}
Hải Phong
  • 5,094
  • 6
  • 31
  • 49
1

I think if I just run TexturePacker on each resolution folder, I will get 55 pack.atlas files (instead of 1) and each pack.atlas file will now reference to 57 sprites (instead of 3135 files), the game should run fine, but it's too laborious.

Running the packer 55 times is too laborious, but creating each sprite in 55 different variations is not?

You should come up with a different approach, since this one will not work out. I assume one of your atlas pages is 1024x1024. So roughly 1MB. Having 212 such pages would result in 212MB just for the sprites. And the user will only use ONE such set of sprites, resulting actively using 1MB, but still carrying 211MB of useless other sprite sets around.

Furthermore by not grouping your assets in any sane way (like 1 atlas for each resolution) you completely destroy the purpose of an atlas. The TextureAtlas is used to reduce the amount of OpenGL texture bindings which reduce performance. But in your case the resulting atlas has all needed assets anywhere in those 212 pages. That means while rendering, behind the scenes you will still have lots of texture bindings, because of those 212 pages and scattered sprites.

You might have a look at Viewport. It helps you dealing with different resolutions and there are many strategies implemented. You should rather use this approach than supplying one set of sprites for each possible resolution. If you want pixel perfect sprite rendering for each resolution, you will still need those 55 different variations, but then you need to repack 55 versions of your app instead of packing 55 versions in one single app.

noone
  • 19,520
  • 5
  • 61
  • 76
  • 1. I use Illustrator to create my sprites, and export them into 55 different versions at once, so it's not laborious. 2. Actually the resulting size of 212 pages is only 5MB, I too was suprised when knowing it was this small so I think it's fine 3. Yes now I understand I should not group all into 1 single atlas. 4. I still want pixel perfect, and I have figured out how to pack into 55 atlas automatically, please check my answer :) – Hải Phong Jun 21 '14 at 07:57