Libgdx schwarze Rechtecke Problem

7

Ich arbeite an einem Spiel für Android mit Android Studio mit LibGDX in Java. Ich habe kürzlich ein seltsames Problem beim Schließen und erneuten Öffnen des Spiels festgestellt. Wenn ich das Spiel zum ersten Mal öffne, funktioniert es einwandfrei. Wenn ich auf die Schaltfläche BEENDEN klicke und die App schließe, verfügt der Vermögensverwalter darüber. Wenn ich das Spiel erneut öffne, werden einige der Atlasregionen als schwarze Rechtecke in derselben Größe der Region angezeigt. Mir ist aufgefallen, dass dies nur passiert, wenn ich die Entsorgungsmethode des Vermögensverwalters aufrufe. Wenn ich es entferne, tritt das Problem nicht auf. Es ist lustig, aber das Spiel scheint gut zu funktionieren, wenn man diese Methode nicht aufruft, aber ich habe gelesen, dass es empfohlen wird, sie zu entsorgen. Dies ist meine AssetsManager-Klasse:

public final class AssetManagerWrapper extends AssetManager {
    ArrayMap<String, FileHandle> configs = new ArrayMap<String, FileHandle>();
    public Texture lightTexture;
    public Texture alarmTexture;
    public TextureAtlas particlesAtlas;

    public final void loadGFX() {
        FileHandle dirHandle;
        dirHandle = Gdx.files.internal(Rules.System.GFX.GFX_FOLDER_NAME);
        FileHandle subDirHandle;

        for (FileHandle dir : dirHandle.list()) {
            subDirHandle = Gdx.files.internal(dir.path());
            if (dir.name().equalsIgnoreCase(AssetsPaths.Gfx.Sheets.SHEETS_FOLDER_NAME)) {
                for (FileHandle file : subDirHandle.list()) {
                    if (file.extension().equalsIgnoreCase(Rules.System.GFX.SHEETS_DATA_EXTENSION)) {
                        load(file.path(), TextureAtlas.class);
                    }
                }
            } else {
                for (FileHandle file : subDirHandle.list()) {
                    load(file.path(), Texture.class);
                }
            }
        }
    }

    public final void loadSounds() {
        FileHandle dirHandle;
        dirHandle = Gdx.files.internal(Rules.System.SFX.SFX_FOLDER_NAME);
        FileHandle subDirHandle;

        for (FileHandle dir : dirHandle.list()) {
            subDirHandle = Gdx.files.internal(dir.path());
            if (dir.name().equalsIgnoreCase(Rules.System.SFX.SOUNDS_FOLDER_NAME)) {
                for (FileHandle file : subDirHandle.list()) {
                    if (file.extension().equalsIgnoreCase(Rules.System.SFX.SOUNDS_DATA_EXTENSION)) {
                        load(file.path(), Sound.class);
                    }
                }
            }
        }

    }

    public void loadParticlesConfigs() {
        FileHandle dirHandle;
        dirHandle = Gdx.files.internal(AssetsPaths.Configs.CONFIGS_FOLDER_NAME + '/' + AssetsPaths.Configs.PARTICLE_CONFIGS_FOLDER_NAME);

        for (FileHandle file : dirHandle.list()) {
            if (file.extension().equalsIgnoreCase(Rules.System.GFX.PARTICLE_CONFIGS_DATA_EXTENSION)) {
                configs.put(file.nameWithoutExtension(), file);
            }
        }
    }


    public final void loadMusic() {
        FileHandle dirHandle;
        dirHandle = Gdx.files.internal(Rules.System.SFX.SFX_FOLDER_NAME);
        FileHandle subDirHandle;

        for (FileHandle dir : dirHandle.list()) {
            subDirHandle = Gdx.files.internal(dir.path());
            if (dir.name().equalsIgnoreCase(Rules.System.SFX.MUSIC_FOLDER_NAME)) {
                for (FileHandle file : subDirHandle.list()) {
                    if (file.extension().equalsIgnoreCase(Rules.System.SFX.MUSIC_DATA_EXTENSION)) {
                        load(file.path(), Music.class);
                    }
                }
            }
        }

    }

    public void loadData() {
        loadGFX();
        loadSounds();
        loadMusic();
        loadParticlesConfigs();
        finishLoading();
    }

    @Override
    public void finishLoading() {
        super.finishLoading();
        lightTexture = get(AssetsPaths.Gfx.Other.LIGHT);
        alarmTexture = get(AssetsPaths.Gfx.Menu.ALARM);
        particlesAtlas = get(AssetsPaths.Gfx.Sheets.Misc.PARTICLES_DATA_FILE);
    }

    public ArrayMap<String, FileHandle> getConfigs() {
        return configs;
    }
}

Der Lebenszyklus (Hauptklasse, die Application Listener implementiert):

   @Override
        public void create() {
            assetsManager = new AssetManagerWrapper();
            assetsManager.loadData();
            soundPlayer = new SoundPlayer(this);
            Gdx.input.setCatchBackKey(true);
            goToMenu();
        }

     @Override
    public void resume() {
        assetsManager.finishLoading();
    }
 @Override
    public void dispose() {
        assetsManager.dispose(); //For some reason this creates the black rectangles bug.
        soundPlayer.dispose();
        if (warScreen != null) {
            warScreen.dispose();
        }
        menuScreen.dispose();
    }

Hat jemand eine Idee, was es verursachen könnte? Ist das in Ordnung, dass ich den Aufruf dieser Methode einfach entferne? Danke im Voraus.

Gad Wissberg
quelle
Was ist der Lebenszyklus Ihrer AssetManagerWrapperKlasse? Wer ruft an loadDataund wann und wer ruft an disposeund wann?
Bornander
AssetsManager.loadData (); wird in onCreate () der Application Listener-Klasse aufgerufen. AssetsManager.dispose (); wird in dispose () derselben Klasse aufgerufen.
Gad Wissberg

Antworten:

0

Gemäß diesem Abschnitt auf der AssetManager-Seite. Wenn Android pausiert, werden die verwalteten libgdx-Elemente wie Textures bereinigt und müssen neu geladen werden, wenn die App fortgesetzt wird. Dazu rufen Sie Texture.setAssetManager(manager);den Asset Manager auf und rufen dann die Aktualisierung auf, wie Sie es beim ersten Laden getan haben.

Zweitens können Android-Apps nicht garantieren, dass sie beim Beenden wirklich nicht mehr ausgeführt werden. Android ist derjenige, der wählt, wenn eine App im Hintergrund bereinigt wird. Obwohl Sie "Beenden" ausgewählt haben, wurde Ihre App möglicherweise noch ausgeführt und die Texturen mussten erneut geladen werden.

spektakulärer Bob
quelle
Ich habe versucht, diese Zeilen in onResume der Hauptklasse einzufügen: Texture.setAssetManager (AssetsManager); AssetsManager.update (); Hat aber nicht funktioniert.
Gad Wissberg
0

Hatte gerade das gleiche Problem. Das Problem war, dass ich einige Texturbereiche als statische Felder hatte. Und um zu vermeiden, dass Texturbereiche für jedes Objekt immer wieder gefunden werden, habe ich eine zusätzliche statische Variable "intitialisiert" hinzugefügt, sodass ich Bereiche nur für das zuerst generierte Objekt gefunden habe, diese Variable für "wahr" festgelegt habe und alle anderen Bereiche übersprungen haben. Das funktioniert gut, wenn ich das Spiel zum ersten Mal starte. Aber wenn ich die App beende und erneut starte und sie im Telefonspeicher verbleibt, behält diese statische "initialisierte" Variable auch ihren Wert bei, was bedeutet, dass Suchregionen nicht erneut aufgerufen wurden. Und alte Regionen existierten, aber ihr Gedächtnis war geleert, so dass ich beim Zeichnen nur schwarze Rechtecke für sie bekam.

Gelöst durch erneutes Aufrufen von findRegion ().

MilanG
quelle