Search code examples
androidlibgdxassetsandroid-assets

Libgdx AssetsManager as static variable


I am trying to implement the AssetsManager to my app. It should only load all the font files and a background music. All this works perfectly. My problem is that sometimes on android the AssetsManger files are away/wrong/buggy when I leave the App and rejoin it later on. I know this is because the life time of the assets is different on Android as the static Variable, thats why this issues occure. My question is how to fix this? The AssetsManager HAS to be static, otherwise I am not able to get the assets from an other class.

My code so far (how to improve?):

public class Colors extends ApplicationAdapter {
//MAIN
private GameStateManager gsm;
private SpriteBatch sb;
private boolean tomenu = false;

//STATIC
public static int WIDTH = 480;
public static int HEIGHT = 800;

//Generell
private FreeTypeFontGenerator fontGenerator;
private FreeTypeFontGenerator.FreeTypeFontParameter fontParameter;
private BitmapFont font;
private Texture loaderb;
private Texture loader;
private Texture timelablogo;

//Asset Manager
public static AssetManager manager = new AssetManager();


@Override
public void create () {
    Gdx.gl.glClearColor(71/255f, 92/255f, 141/255f, 1);
    WIDTH = Gdx.graphics.getWidth();
    HEIGHT = Gdx.graphics.getHeight();

    Gdx.input.setCatchBackKey(true); //Backkey is catched and does not close the App
    gsm = new GameStateManager();
    sb = new SpriteBatch();
    font = new BitmapFont();
    loaderb = new Texture("Buttons/loadingbackground.png");
    loader = new Texture("Buttons/loader.png");
    timelablogo = new Texture("timelab.png");

    //ASSETMANAGER (alle assets[texturen,schirftne,sounds,..])
    manager.load("Sound/menubackground.ogg", Music.class);

    //FreetypeFontGenerator zum AssetManager hinzufügen
    FileHandleResolver resolver = new InternalFileHandleResolver();
    manager.setLoader(FreeTypeFontGenerator.class, new FreeTypeFontGeneratorLoader(resolver));
    manager.setLoader(BitmapFont.class, ".ttf", new FreetypeFontLoader(resolver));

    //Create Fonts and give them to the AssetManager
    FreetypeFontLoader.FreeTypeFontLoaderParameter params1 = new FreetypeFontLoader.FreeTypeFontLoaderParameter();
    params1.fontFileName = "Fonts/kenvector_future1.ttf";
    params1.fontParameters.size = WIDTH/7;
    params1.fontParameters.color = Color.DARK_GRAY;
    manager.load("Fonts/kenvector_future1.ttf", BitmapFont.class, params1);
    FreetypeFontLoader.FreeTypeFontLoaderParameter params2 = new FreetypeFontLoader.FreeTypeFontLoaderParameter();
    params2.fontFileName = "Fonts/kenvector_future2.ttf";
    params2.fontParameters.size = WIDTH/25;
    params2.fontParameters.color = Color.DARK_GRAY;
    manager.load("Fonts/kenvector_future2.ttf", BitmapFont.class, params2);
    FreetypeFontLoader.FreeTypeFontLoaderParameter params3 = new FreetypeFontLoader.FreeTypeFontLoaderParameter();
    params3.fontFileName = "Fonts/kenvector_future3.ttf";
    params3.fontParameters.size = WIDTH/15;
    params3.fontParameters.color = Color.DARK_GRAY;
    manager.load("Fonts/kenvector_future3.ttf", BitmapFont.class, params3);
    FreetypeFontLoader.FreeTypeFontLoaderParameter params4 = new FreetypeFontLoader.FreeTypeFontLoaderParameter();
    params4.fontFileName = "Fonts/kenvector_future4.ttf";
    params4.fontParameters.size = WIDTH/12;
    params4.fontParameters.color = Color.DARK_GRAY;
    manager.load("Fonts/kenvector_future4.ttf", BitmapFont.class, params4);
    FreetypeFontLoader.FreeTypeFontLoaderParameter params5 = new FreetypeFontLoader.FreeTypeFontLoaderParameter();
    params5.fontFileName = "Fonts/kenvector_future5.ttf";
    params5.fontParameters.size = WIDTH/18;
    params5.fontParameters.color = Color.DARK_GRAY;
    manager.load("Fonts/kenvector_future5.ttf", BitmapFont.class, params5);
    FreetypeFontLoader.FreeTypeFontLoaderParameter params6 = new FreetypeFontLoader.FreeTypeFontLoaderParameter();
    params6.fontFileName = "Fonts/kenvector_future6.ttf";
    params6.fontParameters.size = WIDTH/15;
    params6.fontParameters.color.set(99/255f, 99/255f, 99/255f, 1);
    manager.load("Fonts/kenvector_future6.ttf", BitmapFont.class, params6);
}

@Override
public void render () {
    Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
    if(manager.update()) {
        if(!tomenu) {
            tomenu = true;
            manager.get("Sound/menubackground.ogg",Music.class).setLooping(true);
            manager.get("Sound/menubackground.ogg",Music.class).setVolume(0.7f);
            manager.get("Sound/menubackground.ogg",Music.class).play();
            //When everything is loaded a new State is pushed, which uses the font assets from this Assetsmanger
            gsm.push(new MenuStateNew(gsm,0,0,false,1));
        }
        gsm.update(Gdx.graphics.getDeltaTime());
        gsm.render(sb);
        sb.begin();
        font.draw(sb,WIDTH+"px*"+HEIGHT+"px closed BETA v11 "+String.valueOf((int)(1/Gdx.graphics.getDeltaTime()))+" FPS",5,20);
        sb.end();
    } else {
        sb.begin();
        font.draw(sb,WIDTH+"px*"+HEIGHT+"px closed BETA v11 "+String.valueOf((int)(1/Gdx.graphics.getDeltaTime()))+" FPS",5,20);
        sb.draw(loaderb,0,0,WIDTH,WIDTH*0.25f);
        sb.draw(loader,0,0,WIDTH*manager.getProgress(),WIDTH*0.25f);
        sb.draw(timelablogo,WIDTH/2-WIDTH/6,HEIGHT/2-WIDTH/6,WIDTH/3,WIDTH/3);
        sb.end();
    }
}

@Override
public void pause() {
    gsm.pause();
}

@Override
public void dispose () {
    sb.dispose();
    manager.dispose();
    font.dispose();
}

}

EDIT 1:

I implemented the code as you sayed but know the whole game is more dark (no erros)

My code now looks like this (and causes this darker screen :/)

public class Colors extends ApplicationAdapter {
//MAIN
private GameStateManager gsm;
private SpriteBatch sb;
private boolean tomenu = false;

//STATIC
public static int WIDTH = 480;
public static int HEIGHT = 800;

//Generell
private BitmapFont font;
private Texture loaderb;
private Texture loader;
private Texture timelablogo;

//Asset Manager
private Assets assets;


@Override
public void create () {
    Gdx.gl.glClearColor(71/255f, 92/255f, 141/255f, 1);
    WIDTH = Gdx.graphics.getWidth();
    HEIGHT = Gdx.graphics.getHeight();

    //Assetmanager
    assets = new Assets();
    getAssets().load(); //starts loading assets

    Gdx.input.setCatchBackKey(true); //Backkey is catched and does not close the App
    gsm = new GameStateManager();
    sb = new SpriteBatch();
    font = new BitmapFont();
    loaderb = new Texture("Buttons/loadingbackground.png");
    loader = new Texture("Buttons/loader.png");
    timelablogo = new Texture("timelab.png");
}

public static Assets getAssets() {
    return ((Colors) Gdx.app.getApplicationListener()).assets;
}

@Override
public void render () {
    Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
    if(getAssets().manager.update()) {
        if(!tomenu) {
            tomenu = true;
            getAssets().manager.get("Sound/menubackground.ogg",Music.class).setLooping(true);
            getAssets().manager.get("Sound/menubackground.ogg",Music.class).setVolume(0.7f);
            getAssets().manager.get("Sound/menubackground.ogg",Music.class).play();
            gsm.push(new MenuStateNew(gsm,0,0,false,1));
        }
        gsm.update(Gdx.graphics.getDeltaTime());
        gsm.render(sb);
        sb.begin();
        font.draw(sb,WIDTH+"px*"+HEIGHT+"px closed BETA v12 "+String.valueOf((int)(1/Gdx.graphics.getDeltaTime()))+" FPS",5,20);
        sb.end();
    } else {
        sb.begin();
        font.draw(sb,WIDTH+"px*"+HEIGHT+"px closed BETA v12 "+String.valueOf((int)(1/Gdx.graphics.getDeltaTime()))+" FPS",5,20);
        sb.draw(loaderb,0,0,WIDTH,WIDTH*0.25f);
        sb.draw(loader,0,0,WIDTH*getAssets().manager.getProgress(),WIDTH*0.25f);
        sb.draw(timelablogo,WIDTH/2-WIDTH/6,HEIGHT/2-WIDTH/6,WIDTH/3,WIDTH/3);
        sb.end();
    }
}

@Override
public void pause() {
    gsm.pause();
}

@Override
public void resume() { assets.manager.finishLoading(); }

@Override
public void dispose () {
    sb.dispose();
    assets.dispose();
    font.dispose();
}

} And the Assets Class:

public class Assets implements Disposable {

public AssetManager manager = new AssetManager();

public void load() {
    loadMusics();
    loadSounds();
    loadFonts();
}

private void loadSounds() {
    manager.load("Sound/menubackground.ogg", Music.class);
}

private void loadMusics() {
    manager.load("Sound/menubackground.ogg", Music.class);
}

private void loadFonts() {
    //FreetypeFontGenerator zum AssetManager hinzufügen
    FileHandleResolver resolver = new InternalFileHandleResolver();
    manager.setLoader(FreeTypeFontGenerator.class, new FreeTypeFontGeneratorLoader(resolver));
    manager.setLoader(BitmapFont.class, ".ttf", new FreetypeFontLoader(resolver));
    //Create Fonts and give them to the AssetManager
    FreetypeFontLoader.FreeTypeFontLoaderParameter params1 = new FreetypeFontLoader.FreeTypeFontLoaderParameter();
    params1.fontFileName = "Fonts/kenvector_future1.ttf";
    params1.fontParameters.size = WIDTH/7;
    params1.fontParameters.color = Color.DARK_GRAY;
    manager.load("Fonts/kenvector_future1.ttf", BitmapFont.class, params1);
    FreetypeFontLoader.FreeTypeFontLoaderParameter params2 = new FreetypeFontLoader.FreeTypeFontLoaderParameter();
    params2.fontFileName = "Fonts/kenvector_future2.ttf";
    params2.fontParameters.size = WIDTH/25;
    params2.fontParameters.color = Color.DARK_GRAY;
    manager.load("Fonts/kenvector_future2.ttf", BitmapFont.class, params2);
    FreetypeFontLoader.FreeTypeFontLoaderParameter params3 = new FreetypeFontLoader.FreeTypeFontLoaderParameter();
    params3.fontFileName = "Fonts/kenvector_future3.ttf";
    params3.fontParameters.size = WIDTH/15;
    params3.fontParameters.color = Color.DARK_GRAY;
    manager.load("Fonts/kenvector_future3.ttf", BitmapFont.class, params3);
    FreetypeFontLoader.FreeTypeFontLoaderParameter params4 = new FreetypeFontLoader.FreeTypeFontLoaderParameter();
    params4.fontFileName = "Fonts/kenvector_future4.ttf";
    params4.fontParameters.size = WIDTH/12;
    params4.fontParameters.color = Color.DARK_GRAY;
    manager.load("Fonts/kenvector_future4.ttf", BitmapFont.class, params4);
    FreetypeFontLoader.FreeTypeFontLoaderParameter params5 = new FreetypeFontLoader.FreeTypeFontLoaderParameter();
    params5.fontFileName = "Fonts/kenvector_future5.ttf";
    params5.fontParameters.size = WIDTH/18;
    params5.fontParameters.color = Color.DARK_GRAY;
    manager.load("Fonts/kenvector_future5.ttf", BitmapFont.class, params5);
    FreetypeFontLoader.FreeTypeFontLoaderParameter params6 = new FreetypeFontLoader.FreeTypeFontLoaderParameter();
    params6.fontFileName = "Fonts/kenvector_future6.ttf";
    params6.fontParameters.size = WIDTH/15;
    params6.fontParameters.color.set(99/255f, 99/255f, 99/255f, 1);
    manager.load("Fonts/kenvector_future6.ttf", BitmapFont.class, params6);
}

@Override
public void dispose() {
    manager.dispose();
}

} MenuStateNew Class (only an except):

public class MenuStateNew extends State implements GestureDetector.GestureListener {
//Generel
private int width = Colors.WIDTH;
private int height = Colors.HEIGHT;
private GestureDetector gsdt;
private float zeit;
private int mode;

//Buttons
private Texture btn_settings;
private Texture btn_settingsh;
private Sprite sp_settings;
private Rectangle ra_settings;
private Texture btn_easy;
private Texture btn_easyh;
private Texture btn_hard;
private Texture btn_hardh;
private Sprite sp_easy;
private Rectangle ra_easy;
private Texture btn_start;
private Texture btn_starth;
private Sprite sp_start;
private Rectangle ra_start;
private Texture btn_list;
private Rectangle ra_list;

//Fonts
private BitmapFont menufont = Colors.getAssets().manager.get("Fonts/kenvector_future6.ttf", BitmapFont.class);

//Background
private Array<Backgrounddot> backgrounddots;

//Sounds
private Sound s_click;

//Particle Effects
private ParticleEffect pe1;
private ParticleEffect pe2;

//Speicher
Preferences prefs;

public MenuStateNew(GameStateManager pgsm,int plastscore,int plastlevel,boolean highscore,int pmode) {
    super(pgsm);
    //Generell
    gsdt = new GestureDetector(this);
    Gdx.input.setInputProcessor(gsdt);
    mode = pmode;//1: easy,0: hard
}

@Override
public void render(SpriteBatch sb) {
    sb.begin();
    //Particles
    pe1.draw(sb);
    pe2.draw(sb);
    //BackgroundDots
    for(Backgrounddot bgd : backgrounddots) {
        sb.draw(bgd.getTxt_dot(),bgd.getDotposition().x,bgd.getDotposition().y,bgd.getDotwidth(),bgd.getDotwidth());
    }
    sb.draw(sp_settings,ra_settings.getX(),height-ra_settings.getY()-ra_settings.getHeight(),ra_settings.getWidth(),ra_settings.getHeight());
    sb.draw(btn_list,ra_list.getX(),height-ra_list.getY()-ra_list.getHeight(),ra_list.getWidth(),ra_list.getHeight());
    sb.draw(sp_easy,ra_easy.getX(),height-ra_easy.getY()-ra_easy.getHeight(),ra_easy.getWidth(),ra_easy.getHeight());
    sb.draw(sp_start,ra_start.getX(),height-ra_start.getY()-ra_start.getHeight(),ra_start.getWidth(),ra_start.getHeight());
    if(mode == 1) {
        menufont.draw(sb,"Last: "+prefs.getInteger("lastscore2")+" ("+prefs.getInteger("lastlevel2")+")",width/6,height*0.63f);
        menufont.draw(sb,"Best: "+prefs.getInteger("highscore2"),width/6,height*0.515f);
        menufont.draw(sb,"Level "+prefs.getInteger("level2"),width/6,height*0.4f);
    } else if(mode == 0) {
        menufont.draw(sb,"Last: "+prefs.getInteger("lastscore")+" ("+prefs.getInteger("lastlevel")+")",width/6,height*0.63f);
        menufont.draw(sb,"Best: "+prefs.getInteger("highscore"),width/6,height*0.515f);
        menufont.draw(sb,"Level "+prefs.getInteger("level"),width/6,height*0.4f);
    }
    sb.end();
}

Did I somethign wrong?


Solution

  • You should make a class where you store your assets.

    public class Assets implements Disposable {
    
     public AssetManager manager = new AssetManager();
    
     public void load() {
         manager.load("data/mytexture.png", Texture.class);
         manager.load("data/myfont.fnt", BitmapFont.class);
         manager.load("data/mymusic.ogg", Music.class);
     }
    
     @Override
     public void dispose() { 
        manager.dispose();
     }
    }
    

    Keep reference of Your Assets object in Game(Main) class and pass it as reference where it needed.

    public class Colors extends ApplicationAdapter {
    
      Assets assets;
    
      @Override
      public void create() {
    
        assets = new Assets();
        assets.load(); //starts loading assets
    
    
        assets.manager.finishLoading(); //Continues when done loading.
        //it won't continue until all assets are finished loading.
      }
    
     @Override
     public void dispose() {
        assets.dispose();
     }  
    }
    

    EDIT

    Get or initialize all your Private data member(resources) in constructor and then use in render method.

    private BitmapFont menufont;
    
    public MenuStateNew(GameStateManager pgsm,int plastscore,int plastlevel,boolean highscore,int pmode) {
        super(pgsm);
        //Generell
        gsdt = new GestureDetector(this);
        Gdx.input.setInputProcessor(gsdt);
        mode = pmode;//1: easy,0: hard
    
        menufont = Colors.getAssets().manager.get("Fonts/kenvector_future6.ttf", BitmapFont.class);
    }
    

    This is just one example for menufont, same like you need to initialize all required resources in MenuStateNew in his constructor.