Libgdx AssetsManager 作为静态变量

Libgdx AssetsManager as static variable

我正在尝试在我的应用程序中实施 AssetsManager。它应该只加载所有字体文件和背景音乐。所有这一切都很完美。我的问题是,有时在 android 上,AssetsManger 文件是 away/wrong/buggy 当我离开应用程序并稍后重新加入时。我知道这是因为 Android 作为静态变量的资产生命周期不同,这就是为什么会出现这个问题。我的问题是如何解决这个问题? AssetsManager 必须是静态的,否则我无法从其他 class.

获取资产

到目前为止我的代码(如何改进?):

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();
}

}

编辑 1:

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

我的代码现在看起来像这样(并导致屏幕变暗 :/)

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();
}

} 和资产 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(只有一个例外):

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();
}

我是不是搞错了什么?

你应该做一个 class 来存放你的资产。

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();
 }
}

在游戏(主)中保留您的资产对象的引用 class 并将其作为引用传递给需要的地方。

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();
 }  
}

编辑

在构造函数中获取或初始化所有私有数据成员(资源),然后在渲染方法中使用。

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);
}

这只是menufont的一个例子,就像你需要在他的构造函数中初始化MenuStateNew中所有需要的资源一样。

我将通过提供一个必须将 Assets class 传递给所有游戏对象的解决方法来扩展 Abhishek 的回答。

这种方法肯定不是 'best design',但它既方便又安全(据我所知)。

按照 Abhishek 的步骤创建 Assets class,然后您可以在 GdxGame class 中添加以下函数(基础 class)

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

现在,只要您需要纹理或某些资产,就可以调用 GdxGame.getAssets().getTextureRegion(...)。这样你实际上可以在静态的基础上访问资产(方便)并且仍然将资产管理器作为实例变量(安全)。

PS。我在移动设备上,因此,对于格式不正确的问题,我们深表歉意。