Hi, people!
I’m new at game development. I just wrote some games to learn the basic structure and now I’m trying to go with a real game.
Well, I’m using libgdx. I created my own Game State Manager instead of using the Game/Screen, because they don’t save state. That way, I’m using an abstract class called GameState:
public abstract class GameState {
protected GameStateManager gsm;
public abstract void update();
public abstract void render();
public abstract void dispose();
}
The GameStateManager class is just a Stack:
public class GameStateManager {
public Stack<GameState> states;
public GameStateManager(){
System.out.println("Constructor do "+this.toString()+" criado");
states = new Stack<GameState>();
}
public void addState(GameState state){
states.push(state);
}
public void setState(GameState state){
if(!states.empty()){
states.pop();
states.push(state);
} else {
states.push(state);
}
}
public void removeState(){
if(!states.empty()) {states.pop();}
}
public GameState getState(){
return states.peek();
}
public void update(){
states.peek().update();
}
public void render(){
states.peek().render();
}
public void dispose(){
states.peek().dispose();
}
}
And the main game class is pretty simple:
public class MainGame extends ApplicationAdapter {
private static final String TAG = Chemeng.class.getName();
private GameStateManager gsm;
@Override
public void create () {
gsm = new GameStateManager();
gsm.setState(new SplashState(gsm));
}
@Override
public void render () {
input();
gsm.update();
gsm.render();
System.out.printf(" GSM %s: %d%n", gsm.states.peek().toString(), this.gsm.states.size());
}
@Override
public void dispose () {
gsm.dispose();
}
private void input(){
if(Gdx.input.isKeyJustPressed(Keys.ESCAPE)){
Gdx.app.exit();
}
}
}
It’s working fine, besides a crazy loop for me. I have the MainMenuState where the player will choose their options (play campaing, tutorials, load, save, settings, etc, etc). One of them take to the LevelState, what also works fine.
The problem is at the LevelState. Somehow, if we click at the same area from the button in the MainMenuState it works! But the LevelState there is no Stage and no listeners! I checked the GameStateManager and etc and nothing makes sense to me. Anyone knows how it’s happening?
MainMenuState:
public class MainMenuState extends GameState {
private Stage stage;
private Skin skin;
private TextureAtlas uiAtlas;
private Image imgBackground, imgCampanha, imgTutorial, imgCenario;
private Image imgSandbox, imgConfig, imgCreditos;
public MainMenuState(GameStateManager gsm){
System.out.println("Constructor do "+this.toString()+" criado");
this.gsm = gsm;
stage = new Stage(new ScreenViewport());
Gdx.input.setInputProcessor(stage);
uiAtlas = new TextureAtlas(
Gdx.files.internal("skin/uiskin.atlas"));
skin = new Skin(
Gdx.files.internal("skin/uiskin.json"),
uiAtlas);
Texture background = new Texture("img/menu/chemical_plant_menu_background.jpg");
imgBackground = new Image(background);
imgBackground.addAction(Actions.alpha(0.15f));
imgCampanha = new Image(new Texture("img/menu/executive_menu.png"));
imgCampanha.setPosition(750, 500);
imgCampanha.addListener(new InputListener(){
@Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button){
System.out.println("Imagem da campanha clicada...");
teste();
return true;
}
});
imgTutorial = new Image(new Texture("img/menu/estudante_menu.png"));
imgTutorial.setPosition(710, 250);
imgCenario = new Image(new Texture("img/menu/engineer_menu.png"));
imgCenario.setPosition(480, 230, 10);
imgSandbox = new Image(new Texture("img/menu/crazy_scientist_menu.png"));
imgSandbox.setPosition(50, 520);
imgConfig = new Image(new Texture("img/menu/quimica_menu.png"));
imgConfig.setPosition(50, 50);
stage.addActor(imgBackground);
stage.addActor(imgCampanha);
stage.addActor(imgTutorial);
stage.addActor(imgCenario);
stage.addActor(imgSandbox);
stage.addActor(imgConfig);
stage.addAction(Actions.alpha(0));
stage.addAction(Actions.fadeIn(2));
}
private void teste(){
System.out.println("Método teste() chamado;");
System.out.println("Removendo Actor");
stage.addAction(Actions.removeActor(imgCampanha));
imgCampanha = null;
System.out.println("Atualizando GSM para o novo LevelState");
gsm.setState(new LevelState(gsm));
}
@Override
public void update() {
}
@Override
public void render() {
Gdx.gl.glClearColor(0, 0.10f, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
stage.act();
stage.draw();
}
@Override
public void dispose() {
stage.dispose();
}
}
LevelState:
public class LevelState extends GameState {
private OrthographicCamera camera;
private SpriteBatch batch;
private ShapeRenderer shaperenderer;
private Texture map;
public LevelState(GameStateManager gsm){
System.out.println("Constructor do "+this.toString()+" criado");
this.gsm = gsm;
batch = new SpriteBatch();
camera = new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
camera.translate(camera.viewportWidth/2, camera.viewportHeight/2);
camera.update();
map = new Texture(Gdx.files.internal("img/map_test_camera.png"));
shaperenderer = new ShapeRenderer();
}
private void drawUI(){
shaperenderer.begin(ShapeRenderer.ShapeType.Filled);
shaperenderer.setColor(Color.FIREBRICK);
shaperenderer.rect(Gdx.graphics.getWidth()-120, 0, 120, Gdx.graphics.getWidth());
shaperenderer.rect(0, 0, Gdx.graphics.getWidth(), 100);
shaperenderer.end();
}
@Override
public void update() {
}
@Override
public void render() {
Gdx.gl.glClearColor(0, 0.1f, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
camera.update();
batch.setProjectionMatrix(camera.combined);
batch.begin();
batch.draw(map, 0, 0);
batch.end();
drawUI();
camera.translate(1f, 1f);
}
@Override
public void dispose() {
batch.dispose();
map.dispose();
shaperenderer.dispose();
}
}
I even tried to remove the Actor that calls the listener as you can see at teste() method, but even this doesn’t work.
I’m completly lost =[