ImageButton is visible only after resize/resume - Libgdx

I have a class called “HudBarView” which takes care of the drawing of the HUD Bar at the top of the screen(Pause button, score, etc).

This class extends the Group class(scene2d).

Another class I have is “HUDManager” which takes care of all the HUD work in the game, including HUD Bar.

Now, currently I have only a pause button in my HUD Bar but the problem is - it is visible only after I resize or pause and then resume the screen. Very weird problem.

Here is my HudBarView class:

package views.hud.views;

import views.renderers.HUDManager;

import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.scenes.scene2d.Group;
import com.badlogic.gdx.scenes.scene2d.ui.ImageButton;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;

import engine.helpers.AssetsManager;
import engine.helpers.Values;

public class HUDBarView extends Group{

    private ImageButton pause;
    private HUDManager hud_manager;
    private Skin skin;
    public HUDBarView(HUDManager hud_manager) {
        this.hud_manager = hud_manager;
        initiate();
    }
    private void initiate() {
        skin = new Skin(AssetsManager.getAsset(Values.BUTTONS_PACK, TextureAtlas.class));
        pause = new ImageButton(skin.getDrawable("pause"));
        pause.setSize(Values.Pause_Width, Values.Pause_Height);
        pause.setPosition(Values.SCREEN_WIDTH - pause.getWidth(), Values.SCREEN_HEIGHT- pause.getHeight());
        addActor(pause);
    }
}

Here is my HUDManager class:

package views.renderers;

import views.hud.ParticleEffectsActor;
import views.hud.views.HUDBarView;
import aurelienribon.tweenengine.TweenManager;

import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.scenes.scene2d.Group;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.ui.Image;
import com.badlogic.gdx.scenes.scene2d.ui.Label;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;

import engine.helpers.AssetsManager;
import engine.helpers.UIHelper;
import engine.helpers.Values;

public class HUDManager extends Group {

    private Stage stage;
    private Skin skin;
    private Image text;
    private HUDBarView hudView;

    public HUDManager(Stage stage) {
        this.stage = stage;
        initiate();
        addActor(hudView);
        addActor(particles);
    }

    public void initiate() {
        skin = AssetsManager.getAsset(Values.GAME_SKIN_PACK, Skin.class);
        hudView = new HUDBarView(this);
        particles = new ParticleEffectsActor();
    }

    public Stage getStage() {
        return stage;
    }
}

Here are some photos that will help you understand the problem a little bit better: Before the screen is resized(it doesn’t matter how much the screen is resized):

After the screen is resized:

P.S Here is my Game Screen class:


package views.screens;

import views.renderers.GameRenderer;
import views.renderers.HUDManager;
import engine.GameInputHandler;
import engine.GameWorld;
import engine.Values;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.InputMultiplexer;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.utils.viewport.StretchViewport;

/* Created by David Lasry : 10/25/14 */
public class GameScreen extends ScreenWrapper {

	private GameWorld world;
	private HUDManager hudManager;
	private Stage stage;

	public GameScreen() {
		super();
		ScreenHandler.getInstance().getGame().getAssetsManager().loadAsstes(2, this);
		world = new GameWorld();
		stage = new Stage(new StretchViewport(Values.SCREEN_WIDTH,
				Values.SCREEN_HEIGHT));
		camera = (OrthographicCamera) stage.getCamera();
		batch = (SpriteBatch) stage.getBatch();
		InputMultiplexer inputs = new InputMultiplexer();
		inputs.addProcessor(stage);
		inputs.addProcessor(new GameInputHandler(world.getMonkeyManager(),
				camera));
		Gdx.input.setInputProcessor(inputs);
	}

	@Override
	public void render(float delta) {
		switch (state) {
		case RUN:
			renderer.render(delta);
			stage.act(delta);
			stage.draw();
			world.update(delta);
			break;
		case PAUSE:
			break;
		}
	}

	// Callback method that is called when the assets are loaded
	@Override
	public void assetsLoaded() {
		renderer = new GameRenderer(world, camera, batch);
		hudManager = new HUDManager();
		stage.addActor(hudManager);
	}

	public HUDManager getHudManager() {
		return hudManager;
	}

	@Override
	public void dispose() {
		super.dispose();
		stage.dispose();
		ScreenHandler.getInstance().getGame().getAssetsManager().unload(2);
	}
}


I don’t understand what is the problem?

EDIT: Here is my screen wrapper class:

package views.screens;

import com.badlogic.gdx.Screen;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;

/* Created by David Lasry : 31/10/14 */
public abstract class ScreenWrapper implements Screen{

	protected State state;
	protected OrthographicCamera camera;
	protected SpriteBatch batch;
	public ScreenWrapper() {
		state = State.RUN;
	}
	@Override
	public abstract void render(float delta);
	public abstract void assetsLoaded();
	public OrthographicCamera getCamera() {
		return camera;
	}
	public SpriteBatch getBatch() {
		return batch;
	}
	@Override
	public void resize(int width, int height) {
		
	}

	@Override
	public void show() {
		
	}

	@Override
	public void hide() {
		
	}

	@Override
	public void pause() {
		state = State.PAUSE;
	}

	@Override
	public void resume() {
		state = State.RUN;
	}
}

EDIT!: After playing a little bit with the code, I found out that if I change the position of the ImageButton, it is seen in the screen in the wrong position but when I resize or pause/resume the game, the button is at its right position.

Here is an example: if I change the position of the button from:

Vector2 position = new Vector2(Values.SCREEN_WIDTH - Values.Pause_Width,Values.SCREEN_HEIGHT - Values.Pause_Height);
		pause.setPosition(position.x, position.y);

To:

Vector2 position = new Vector2(Values.SCREEN_WIDTH - Values.Pause_Width,Values.SCREEN_HEIGHT - Values.Pause_Height*2);
		pause.setPosition(position.x, position.y);

The button is at the the top right corner of the screen, which is wrong:

But after resize or pause/resume the window of the game, the button is at:

Which is the correct position.

What is the reason of this? I’m kinda new in scene2d…

Lets see the ScreenWrapper class.

You probably have not set the Stages camera up or something and it is being set on resize.

Thanks for your reply!
I have editted my post and added the ScreenWrapper class. Please take a look :slight_smile:

Weird indeed.

A few things to try. Check if the stage actually contains the actor prior to resize, check if it visible prior to resize (which it should be as default is true).

It’s your code, not Scene2D. That much is clear, probably just a code fart elsewhere :D.

Also top tip, see you have these parts:

/* Created by David Lasry : 10/25/14 */
public class GameScreen extends ScreenWrapper {

If you are using Eclipse, you can just do /** and then hit enter and it will fill it in with:

/**
 *@author NAME_OF_USER_ACCOUNT
 */

You can also add the @since for the date it was created and @version it was added 8).

You can read more HERE.

Thanks for the reply.

Regarding your notes, I did check if the stage contains the actor prior to resize+if the actor is visible prior to resize and it’s still doesn’t work. I think it has something to do with the camera of the stage but I can’t pin point the problem.

Try setting your own camera and viewport like so:


			stage.setViewport(new StretchViewport(width, height, new OrthographicCamera()));

Then in your resize method, do this:

stage.update(width, height);

it doesn’t work. the problem still remains :-\ :’(

Hm,

You are using

addActor()

Which adds the button to the stage without a layout, try just using add() and see if that is the problem. It might not be validating and calling layout on the actors until the camera is resized. Or even do:

button.setPosition(x, y)

I have nothing else on this one :s For me Scene2D is a case of create actor, add…magic happens underneath and it works lol.

Sorry but I can’t find add() method. Are you sure it’s its name?

Could you please help me out? I editted my post and added some new findings

Anyone?..

My advice.

I suggest you take a step back and stop with all the abstraction you got going on at the moment, and write what you want out in a single class and then work from there.

also add() is only available for the Table class I think. You should be using tables anyway, this might have something to do with it.

Regardless, I think you should take a step back from the abstraction and see how it goes from there. I can’t see anything obviously with your code, so I am going to go with the assumption it is just a bad structure and you being new. Give what I said a try, it shouldn’t take long.

I’m trying to do what you said but I still can’t figure out what could be the problem.

Anyone? I’m desperate for help!