Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

libgdx background Image change

I want to change background image of a menu every x-amount of seconds. I'm using libGDX scene2D.ui for making the menu. The TestScreen class extends the AbstractScreen which is a abstract class that implements libGDX's Screen class. Problem: After I load the Image to the stage through a Table object on a stack, changing the image reference to a different image does nothing. Stage.draw() gives no cares as if it made a copy of my original image. I would like to keep the background as Image class and render through stage.draw().

To further complicate things, if I do change the image to another in render() method, then image.setVisible(false) also stops working.

public class TestScreen extends AbstractScreen {

private Stage stage;
private Image background;
private boolean ChangeBackground = true;
private final float refreshTime = 2.0f; // refresh to new image every 2 seconds.
private float counter = refreshTime;

public TestScreen(Game game) {
    super(game);
}

@Override
public void render(float deltaTime) {
    Gdx.gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);

    if(ChangeBackground){
        counter -= deltaTime;
        if(counter < 0){
            counter = refreshTime;
            // Assets class has the 12 images loaded as "Image" objects already.
            // I simple want to change the reference to other (already loaded in memory images) ...
            // and make stage render the new image.
            background = Assets.instance.wallpapers[(int) (Math.random()*12)];  // The image should change.
            //background.setVisible(false);
        }
    }
    stage.act(deltaTime);
    stage.draw();
}

@Override
public void resize(int width, int height) {
    stage.setViewport(Constants.VIEWPORT_GUI_WIDTH, Constants.VIEWPORT_GUI_HEIGHT, false);
}
@Override
public void show() {
    stage = new Stage();
    Gdx.input.setInputProcessor(stage);
    makeStage();
}
@Override
public void hide() {
    stage.dispose();
}
@Override
public void pause() {   
}

// Builds the Background later and adds it to a stage through a stack.
// This is how it's done in my game. I made this test bench to demonstrate.
private void makeStage() {
    Table BackGroundLayer = new Table();
    background = Assets.instance.wallpapers[(int) (Math.random()*12)];
    BackGroundLayer.add(background);

    Stack layers = new Stack();
    layers.setSize(800, 480);
    layers.add(BackGroundLayer);

    stage.clear();
    stage.addActor(layers);
}

}

like image 632
Artash Avatar asked Mar 21 '23 15:03

Artash


1 Answers

Image is a subclass of Actor. The main difference is, that Image has a Drawable inside. This Drawable gets drawn if you call stage.draw(), which calls the draw() of Image. Instead of changing Image you can change the Drawable by using setDrawable(Drawable param);. What is a Drawable? It is any class, which implements the Drawable interface, for example the TextureRegionDrawable. If you are using TextureRegions you can use this constructor: TextureRegionDrawable(TextureRegion region);. Maybe it would be better to store your background images in a Drawable Array so you don't have to call a construcor each time you set a new Drawable. Example code:

TextureRegionDrawable[] images = new TextureRegionDrawable[12];
for (int i = 0; i<12; i++) {
    images[i] = new TextureRegionDrawable(Assets.instance.textureRegions[i]);
}

Then in your render:

if(changeBackground) {
   counter -= delta;
   if (counter < 0) {
       counter = refreshtime
       background.setDrawable(images[(int)(Math.random()*12)]);
   }
}

This should work

like image 107
Robert P Avatar answered Mar 31 '23 21:03

Robert P