0
\$\begingroup\$

In the main Screen class of my game there is a ListArray<Card> which makes up the deck of cards . The Card's texture is set in the constructor like so :

cardTexture = new Texture(Gdx.files.internal("backface.png"));

and in the Card class there are 2 methods to show and hide the "CardFace"

public void hideCardFace() {
    cardTexture = new Texture(Gdx.files.internal("backface.png"));
}
public void showCardFace() {
    cardTexture = new Texture(("CardTextures/" + this.getFace() + this.getSuit() + ".png"));
}

(in the android\assets\CardTextures there are 52 .png files with a size of 500x726 and rangeing in filesize from 20-220 kb)

The problem is that when I have to show or hide the "CardFace" for the entire ArrayList like so :

for (int i = 0; i < deck.size(); i++) {
    ((Card) deck.get(i)).hideCardFace();
}

I experience a performance drop both on PC and Android to the point where the Game lags for 1-2 seconds until all the CardFaces are hidden or showed.(I did multiple tests and the FPS dips only when I call the 2 methods)

Is there any other way (better for performance) to change the CardFace?

\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

Read about the AssetManager here: https://github.com/libgdx/libgdx/wiki/Managing-your-assets

You are loading new Texture's objects with each card change which equals DEATH. What you should do is have 52 card textures in memory and 1 back card texture, so 53 textures at max.

Your code allocates new ram with every card change you make. It's unacceptable.

Create a class for all the assets for example:

public class Assets{
    private AssetManager assetMgr;
    private static HashMap<CardType, Texture> cardsTextures = new HashMap<>();
    private static Texture faceDownTexture;
    public Assets(){

        assetMgr = new AssetManager():

        // load all the 53 assets with AssetManager

        // assetMgr load...

        // and now put these values from assetManager into the map
        // make a loop or something !
        cardsTextures.put(ACE_OF_SPACES, aceofspadestexture);
        cardsTextures.put(THREE_OF_SPACES, aceofspadestexture);
        cardsTextures.put(SEVEN_OF_SPACES, aceofspadestexture);

        // load faceDownTexture texture for example
        faceDownTexture = new Texture(Gdx.files.internal("cards/facedown.png"));

        cardsTextures.put(FACE_DOWN, faceDownTexture);
    }

    // a method that will give you your textures from anywhere in the code

    public static Texture getCardTexture(CardType type){
        return cardTextures.get(type);
    }

    public static Texture getBackTexture(){
        return backTexture;
    }

}

Use the class above to load all these textures with AssetManager and create your card class like this:

public class Card{

    private Texture cardTexture, backTexture;
    private boolean isFaceUp;

    public Card(CardType type){

        cardTexture = Assets.getCardTexture(type);
        backTexture = Assets.getBackTexture();

        isFaceUp = false;

        setSize(cardTexture.getWidth(), cardTexture.getHeight());

    }

    @Override
    public void draw(Batch batch, float parentAlpha){
        if(isFaceUp)
            batch.draw(cardTexture, getX(), getY(), getWidth(), getHeight());
        else batch.draw(backTexture, getX(), getY(), getWidth(), getHeight());

    }


    public void showFaceUp(boolean b){
        this.isFaceUp = b;
    }
}

This is all pseudocode, but this is the right way.

Then, your 'switching' code should look like this:

// 10000 nanoseconds and 0 RAM!
for (int i = 0; i < deck.size(); i++) {
    ((Card) deck.get(i)).showFaceUp(false);
}
\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .