2017-03-09 4 views
0

Ich habe folgende Enum-Datei "DevelopmentCardType":ExceptionInInitializerError mit Aufzählungen in Libgdx

enum DevelopmentCardType { 
    KNIGHT (0, new Texture(Gdx.files.internal("knight_card.png"))); 
    VICTORY_POINT (1, new Texture(Gdx.files.internal("victory_point_card.png"))), 

    private final Texture cardTexture; 
    private final int type; 
    private static final List<DevelopmentCardType> VALUES = Collections.unmodifiableList(Arrays.asList(values())); 

    DevelopmentCardType(int type, Texture cardTexture) { 
     this.type = type; 
     this.cardTexture = cardTexture; 
    } 

    public Texture getCardTexture() { 
     return cardTexture; 
    } 

    public static List<DevelopmentCardType> getVALUES() { 
     return VALUES; 
    } 
} 

auf einem Sockel Ereignis ein neues DevelopmentCard erstellt

"DevelopmentCard" Klasse:

class DevelopmentCard extends Card { 

    private float[] vertices = { 
     0, 0, 
     512, 0, 
     512, 512, 
     0, 512 
    }; 

    DevelopmentCard (int type) { 
    super(0, 0, 70, 100); 
    this.type = type; 
    createResourceCardSprite(type); 
    } 

    private void createResourceCardSprite(int resourceType) { 
    Texture cardTexture = DevelopmentCardType.getVALUES().get(resourceType).getCardTexture(); 
    TextureRegion textureRegion = new TextureRegion(cardTexture); 
    PolygonRegion polygonRegion = new PolygonRegion(textureRegion, vertices, new EarClippingTriangulator().computeTriangles(vertices).toArray()); 
    card = new PolygonSprite(polygonRegion); 
    } 
} 

Wenn eine neue DevelopmentCard erstellt wird, erstellt sie einen ExceptionInInitializerError "verursacht durch", da kein OpenGL-Kontext vorhanden ist.

Das bedeutet, dass die Texturen, die in der Enumeration verwendet werden, noch nicht erstellt wurden. Deshalb möchte ich das tun, bevor ich die Enumeration bei einem Socket-Ereignis verwende. Ich kann es beheben, indem ich der DevelopmentCardType-Klasse eine init-Methode hinzufüge (ich verstehe, dass das Aufrufen irgendeiner Methode (die wie diese leer sein kann) in der Enumeration noch im OpenGL-Kontext das Problem behebt, ich bin mir nicht sicher, ob das ist das richtige zu tun):

static void init() {} 

und diese in der Klasse "Main" wie DevelopmentCardType.init(); aufrufen.

Ist dies der richtige Weg, um dieses Problem zu umgehen? Ich kann das Problem auch beheben, indem ich eine DevelopmentCard noch im OpenGL-Kontext erstelle, danach führt das Erstellen neuer DevelopmentCard-Instanzen nicht zu Fehlern.

Antwort

1

Es gibt zwei Anforderungen zum Instantiieren einer Textur. Es muss auf dem GL-Thread geschehen, und es muss getan werden, nachdem LibGDX initialisiert wird.

Wenn DevelopmentCardType zum ersten Mal überall referenziert wird, werden alle seine Werte (KNIGHT und VICTORY_POINT) instanziiert. Dies tritt wahrscheinlich auf, bevor die Gdx-Engine initialisiert wird (was passiert, wenn Sie in Ihrem DesktopLauncher oder AndroidLauncher initialisieren). Es tritt wahrscheinlich auch in einem anderen Thread als dem GL-Thread auf, wenn DevelopmentCardType außerhalb Ihrer create() - und render() -Methoden (z. B. im Konstruktor oder als Membervariable) verwendet wird.

Außerdem ist es für eine Enum nicht sinnvoll, das Laden eines Assets (der Texturen) zu handhaben, bei dem es sich um vorübergehende Objekte handelt, die Speicherverluste verursachen, wenn sie nicht ordnungsgemäß entsorgt werden.

Wirklich sollten Sie alle Ihre Vermögenswerte für Ihr Spiel an einem Ort behandeln, so dass Sie einfach zu handhaben und zu entlasten, und Speicherverluste. LibGDX hat dafür bereits eine leistungsfähige Klasse, AssetManager. Wenn Sie eine ähnliche Struktur wie Ihren aktuellen Code beibehalten möchten, sollten Sie den Texture-Member Ihrer Enumeration durch einen String für den Dateinamen der Textur ersetzen. Dies kann verwendet werden, um die Textur von Ihrem AssetManager abzurufen. Sie können Ihre AssetManager-Instanz an Ihren DevelopmentCard-Konstruktor übergeben, damit die Textur abgerufen werden kann.

+0

Ich werde sehen, wenn ich den AssetManager verstehe, werde ich auf diese Antwort zurückkommen. –

+0

Also muss ich die AssetManager-Instanz durch viele Konstruktoren und alle Instanzen von DevelopmentCard und anderen Klassen übergeben? Ist das nicht langsam? Oder meinst du das? –

+0

Ich habe den AssetManager implementiert, der verwendete RAM wurde halbiert, und ich muss jetzt keine Methode aufrufen, bevor ich sie verwenden kann. Danke :) –