0

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?

Tim Jansen
  • 109
  • 1
  • 6

2 Answers2

3

I will expand on Abhishek's answer by providing a workaround for having to pass an Assets class around to all of your game objects.

This approach is most certainly not the 'best design', but it is convenient, and safe (to the best of my knowledge).

Follow Abhishek's steps in creating an Assets class, and from there you can add the following function in your GdxGame class (the base class)

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

Now, whenever you need an texture or some asset, you can call GdxGame.getAssets().getTextureRegion(...). This way you can actually access the assets on a static basis (convenient) and still have the asset manager as an instance variable (safe).

PS. Am on a mobile device, so, apologies for any poor formatting.

Matthew Tory
  • 1,306
  • 2
  • 16
  • 30
0

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.

Abhishek Aryan
  • 19,936
  • 8
  • 46
  • 65
  • does the 'assets.manager.finishLoading();' dont have to be in the redner method? There it updates (loads) the textures right? Also how to make a loading bar and get the AssetsManager data from another class? – Tim Jansen Mar 20 '17 at 15:46
  • finishLoading() method Blocks until the specified asset is loaded. you can call update method in render method that Updates the AssetManager, keeping it loading any assets in the preload queue. Use update method in render and by getProgress() you can get percent of completion of asset loaded that can use to show progressbar. – Abhishek Aryan Mar 20 '17 at 16:02
  • get assets by this ((Colors) Gdx.app.getApplicationListener()).assets; or you can pass assets in constructor from your Colors class. – Abhishek Aryan Mar 20 '17 at 16:04
  • So I can choose if I do assets.manager.finishLoading() for synchronous loading without a loading bar OR call the manager.update() in render method which also loads everything but asynchronous??? – Tim Jansen Mar 20 '17 at 16:53
  • I think this question is how to use non static AssetManager, not how to load assets by finishLoading() or via update() method. I was just giving an example to load your assets. – Abhishek Aryan Mar 20 '17 at 17:47
  • what is gsm.push(new MenuStateNew(gsm,0,0,false,1)); and how you drawing by gsm.render(sb); – Abhishek Aryan Mar 20 '17 at 18:31
  • Its the GameStateManger, it hold all states, the above state is the one which is shown. I made it like this: https://www.youtube.com/watch?v=gR88EZEXEQg (PART 2) and https://www.youtube.com/watch?v=24p1Mvx6KFg (PART 3) – Tim Jansen Mar 20 '17 at 18:46
  • add one parameter to MenuStateNew constructor and pass assets. like this (assets,gsm,0,0,false,1)); use assets in MenuStateNew constructor and create resource and use. – Abhishek Aryan Mar 20 '17 at 18:58
  • MenuState is just one Sate(the first one) but the AssetsManager has lots of Assets, isnt that than not superfluous? – Tim Jansen Mar 20 '17 at 19:11
  • My problem is now, as I posted, that the screen is dark (not normal colors) – Tim Jansen Mar 20 '17 at 19:11
  • you want to see the Menustate class? I have copied it to my edited part – Tim Jansen Mar 20 '17 at 19:13
  • ok I corrected that but it does not solve the problem with the darker screen :/ ? – Tim Jansen Mar 20 '17 at 20:10
  • have you added background to backgrounddots ? – Abhishek Aryan Mar 20 '17 at 20:12
  • Yes the code is fine everything worked perfectly before I started adding the AssetManger – Tim Jansen Mar 20 '17 at 20:20
  • I SOLVED the problem with the dark screen. The problem was that I first had to load the Assets Class at the end of the Colors constructer. – Tim Jansen Mar 21 '17 at 16:43
  • Glad to hear. Good keep it up. – Abhishek Aryan Mar 21 '17 at 16:46