I've been following along with a LibGDX tutorial on Youtube and have come across an issue rendering a TiledMap to my screen. At the moment, I can render some labels/images using my HUD java class
public class HUD {
public Stage stage; //the background
private Viewport viewport; //so the HUD stays fixed and the world can move
private int score;
private int timer;
private int bactoCount;
private Texture foodTexture, antioBioBottle;
//these are widgets
Label antioBioTxt;
Image antiBioImg;
Label countDown;
Label countTxt;
Image foodImg;
Label foodTxt;
Label bactoCountLabel;
Label bactoTxt;
//these images need to be buttons...
public HUD (SpriteBatch sb) {
foodTexture = new Texture("Bacto food.png");
antioBioBottle = new Texture("Antibioticbottle.png");
bactoCount = 0;
timer = 0;
viewport = new FitViewport(BactoBuds.V_WIDTH, BactoBuds.V_HEIGHT, new OrthographicCamera());
stage = new Stage(viewport, sb);
//stage = new Stage();
//use a Table to organise widgets on the stage
Table table = new Table();
table.top();
table.setFillParent(true); //the table is the size of our stage
antioBioTxt = new Label("Antibiotic", new Label.LabelStyle(new BitmapFont(), Color.WHITE));
antiBioImg = new Image(antioBioBottle);
// %03d means its 3 digits long
//bitmap font sets the font to bit style
//string.format for changing from a string to a int
countDown = new Label(String.format("%03d", timer), new Label.LabelStyle(new BitmapFont(), Color.WHITE));
countTxt = new Label("Time to flood:", new Label.LabelStyle(new BitmapFont(), Color.WHITE));
foodImg = new Image(foodTexture);
foodTxt = new Label("Food", new Label.LabelStyle(new BitmapFont(), Color.WHITE));
bactoCountLabel = new Label(String.format("%06d", bactoCount), new Label.LabelStyle(new BitmapFont(), Color.WHITE));
bactoTxt = new Label("Bacteria:", new Label.LabelStyle(new BitmapFont(), Color.WHITE));
//if multiple labels use expandX then they all share an equal portion of the screen
table.add(antioBioTxt).expandX().padTop(10);
table.add(foodTxt).expandX().padTop(10);
table.add(bactoTxt).expandX().padTop(10);
table.add(countTxt).expandX().padTop(10);
table.row();
table.add(antiBioImg).expandX();
table.add(foodImg).expandX();
table.add(bactoCountLabel).expandX().align(Align.center);
table.add(countDown).expandX().align(Align.center);
stage.addActor(table);
}
}
These render nicely on the screen. However, when I try to render up a background TMX map image, it renders in the wrong location. I've been messing with the code for a few days now, trying to change the position of the map position. At the first instance I was only able to see a tiny corner of the map and now I've gotten the whole thing to render, but it only takes up ~1/4 of the screen. Now I am at a loss as to how to proceed.
public class playScreen implements Screen{
private BactoBuds game;
private OrthographicCamera gamecamera;
private Viewport gameView;
private HUD HUD;
private TmxMapLoader mapLoader; //loads map to screen
private TiledMap map; //reference to map
private OrthogonalTiledMapRenderer renderer;
public playScreen (BactoBuds game) {
this.game = game;
gamecamera = new OrthographicCamera();
gameView = new FitViewport(BactoBuds.V_WIDTH, BactoBuds.V_HEIGHT, gamecamera);
HUD = new HUD(game.batch);
mapLoader = new TmxMapLoader(); //make a new map loader, set map to maploader, then pass it to the renderer
map = mapLoader.load("grassy.tmx");
renderer = new OrthogonalTiledMapRenderer(map);
gamecamera.setToOrtho(false);
gamecamera.position.set(gameView.getWorldWidth() / 2, gameView.getWorldHeight() / 2, 0); //this changes map position
renderer.setView(gamecamera);
}
#Override
public void show() {
}
#Override
public void render(float delta) {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
renderer.render();
game.batch.setProjectionMatrix(HUD.stage.getCamera().combined);
HUD.stage.draw();
}
Please forgive the dodgy coding, I'm quite new and I'm still learning about good practices. I think it has something to do with the camera positioning, but swapping out the values doesn't appear to change anything.
public class BactoBuds extends Game {
public static final int V_WIDTH = 800;
public static final int V_HEIGHT = 480;
public static final String Title = "BactoBuds";
public SpriteBatch batch; //public to let other screens have access to images
private Texture img;
private Game game;
private Screen screen;
private OrthographicCamera camera;
public BactoBuds () {
game = this;
}
#Override
public void create () {
batch = new SpriteBatch();
img = new Texture("badlogic.jpg");
// change this to menuScreen later
setScreen(new playScreen(this));
}
public void dispose () {
batch.dispose();
img.dispose();
}
#Override
public void render () {
super.render();
}
public void resume (){
}
public void pause () {
}
}
Thanks for the help!
You need to call camera.update() within render method.
Have you tried moving your camera? If only 1/4 of the map is visible your camera might be centered at 0,0 while your map uses that as the bottom left origin of the texture.
Try camera.position.set(BactoBuds.V_WIDTH / 2, BactoBuds.V_HEIGHT / 2, 0);
Related
I'm new to libGDX I've been trying to follow tutorials on how to create buttons and add textures to them however I am really struggling with it. How would I add textures to the continue and back buttons? I only have the png image and a .pack file for the textures
Also if anyone would be able to suggest some ways I can change the font of the labels I have for my buttons e.g. lbl_ip
Any help would be really appreciated.
public class MenuScreen implements Screen {
private Viewport viewport;
private Stage stage;
#SuppressWarnings("unused")
private MainGame game;
private Label lbl_ip;
private Label lbl_name;
private Label lbl_back;
private LabelStyle lbl_style;
private Skin txt_skin;
private TextButtonStyle btn_style;
private TextField txt_ip;
private TextField txt_name;
//private TextField txt_back;
private Button btn_confirm;
private Button btn_back;
public static String ip = "localhost"; // change with user input
public static String name = "Player 1";
public static String back = "<---";
public MenuScreen(MainGame game) {
this.game = game;
viewport = new FitViewport(MainGame.V_WIDTH/6, MainGame.V_HEIGHT/6, new OrthographicCamera());
stage = new Stage(viewport, ((MainGame) game).batch);
lbl_style = new Label.LabelStyle();
lbl_style.font = new BitmapFont();
txt_skin = new Skin(Gdx.files.internal("uiskin.json"));
btn_style = new TextButton.TextButtonStyle();
btn_style.font = new BitmapFont();
Table table = new Table();
table.top();
table.setFillParent(true);
lbl_ip = new Label("please enter an IP address:" , lbl_style);
lbl_name = new Label("enter your name: " , lbl_style);
lbl_back = new Label("Return to Main Menue", lbl_style);
txt_ip = new TextField(ip, txt_skin);
txt_name = new TextField(name, txt_skin);
//txt_back = new TextField(back, txt_skin);
btn_confirm = new TextButton("confirm", btn_style);
btn_back = new TextButton("<--", btn_style);
table.add(lbl_ip).expandX();
table.add(txt_ip).width(200);
table.row();
table.add(lbl_name).expandX();
table.add(txt_name).width(200);
table.row();
//table.add(lbl_back).expandX();
table.add(btn_back);
//table.add(txt_back).width(200);
table.row();
table.add(btn_confirm);
table.row();
stage.addActor(table);
Gdx.input.setInputProcessor(stage);
}
private void buttonHandler() {
if(Gdx.input.isKeyPressed(Input.Keys.ENTER)) {
/*
game.setScreen(new PlayScreen(game));
*/
txt_ip.setTextFieldListener(new TextField.TextFieldListener() {
#Override
public void keyTyped(TextField textField, char c) {
ip = textField.getText();
}
});
txt_name.setTextFieldListener(new TextField.TextFieldListener() {
#Override
public void keyTyped(TextField textField, char c) {
name = textField.getText();
}
});
new MPClient(txt_ip.getText(), txt_name.getText(), game);
dispose();
}
}
#Override
public void show() {
// TODO Auto-generated method stub
}
#Override
public void render(float delta) {
Gdx.gl.glClearColor(0, 0, 0 , 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
stage.draw();
stage.act(delta);
buttonHandler();
}
#Override
public void dispose() {
stage.dispose();
}
}
You need to use ImageTextButton for that. You need to provide it with ImageTextButtonStyle, which is easy to create (you need to assign its imageUp property, other properties can be null).
As far as label font goes, you need to create a new LabelStyle and assign it a new BitmapFont. An example:
Label lab = new Label("This is the text", new LabelStyle(myFont, Color.RED));
"myfont" is a BitmapFont.
Here is a real-world example how to create a BitmapFont:
FreeTypeFontGenerator generator;
FreeTypeFontParameter parameter;
generator = new FreeTypeFontGenerator(Gdx.files.internal("fonts/nidsans-webfont.ttf"));
parameter = new FreeTypeFontParameter();
parameter.size = 12;
parameter.minFilter = TextureFilter.Linear;
parameter.magFilter = TextureFilter.Linear;
myfont = generator.generateFont(parameter);
You need to change the -style- associated with the widget. And you may want to make a new style per widget rather than sharing a style across all (because that would update all widgets with the new background)
LabelStyle newLabelStyle = new LabelStyle(originalLabel.getStyle());
tobeChangedLabel.setStyle(newLabelStyle);
newLabelStyle.background = new Image( //however you like to make the image
Changing the font is somewhat tricky... as the fonts are baked into the style as bitmaps (for rendering speed). You may find that given you don't like the background of your style, or even the font, that you might want to use a different skin. You can make your own or use one from here.
https://github.com/czyzby/gdx-skins
If you have to dynamically choose font you can dynamically build your bitmaps of rendered fonts with gdx-freetype-font-manager
https://jitpack.io/p/1nt3g3r/gdx-freetype-font-manager
Trying to place two buttons in a table row.
Right-most button appears slightly offscreen.
Adding to table with .add(btn).right() but seems not to have any effect.
Documentation says something about removing the Align.left and vise-versa but I'm not sure what they're saying.
Working from mobile.
Took pic, uploaded to ImageBucket but can't see whole thing so took two more (top + bottom of screen) just in case.
Top of screen:
https://i1161.photobucket.com/albums/q501/StudioGilliam/Screenshot_20190430-224041_TextBasedRPG.jpg
As you can see, the labels display fine.
Bottom of screen:
https://i1161.photobucket.com/albums/q501/StudioGilliam/Screenshot_20190430-224024_TextBasedRPG.jpg
The offending code:
public class TextBasedRPG implements ApplicationListener
{
private Stage stage;
private TextButton btnNext;
private TextButton btnItems;
private Label lblPlayer1;
private Label lblEnemy1;
private Label lblInfo;
#Override
public void create()
{
stage = new Stage(new ScreenViewport());
Gdx.input.setInputProcessor(stage);
// UI STUFF
// Labels
Label.LabelStyle styleL = new Label.LabelStyle(new BitmapFont(), Color.BLACK);
lblPlayer1 = new Label("Player data", styleL);
lblPlayer1.setFontScale(3.5f);
lblEnemy1 = new Label("Enemy data", styleL);
lblEnemy1.setFontScale(3.5f);
lblEnemy1.setAlignment(Align.right);
lblInfo = new Label("Information", styleL);
lblInfo.setFontScale(4.0f);
// Buttons
TextButton.TextButtonStyle styleTB = new TextButton.TextButtonStyle();
styleTB.font = new BitmapFont();
styleTB.up = new NinePatchDrawable(new NinePatch(new Texture(Gdx.files.internal("ButtonGreyUp.png")), 10, 10, 10, 10));
styleTB.down = new NinePatchDrawable(new NinePatch(new Texture(Gdx.files.internal("ButtonGreyDown.png")), 10, 10, 10, 10));
btnNext = new TextButton("Next Turn", styleTB);
btnNext.setTransform(true);
btnNext.setScale(6.0f);
btnNext.setTouchable(Touchable.enabled);
btnNext.align(Align.right);
btnItems = new TextButton("Play", styleTB);
btnItems.setTransform(true);
btnItems.setScale(6.0f);
btnItems.setTouchable(Touchable.enabled);
// Table
Table table = new Table();
table.setBounds(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
table.setFillParent(true);
table.pad(50);
table.add(lblPlayer1).expandX().left();
table.add(lblEnemy1).expandX().right();
table.row();
table.add(lblInfo).expandY().colspan(2);
table.row();
table.add(btnItems).expandX().left();
table.add(btnNext).expandX().right();
table.debugAll();
stage.addActor(table);
}
#Override
public void render()
{
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
stage.act();
stage.draw();
}
#Override
public void dispose(){stage.dispose();}
#Override
public void resize(int width, int height){}
#Override
public void pause(){}
#Override
public void resume(){}
I don't recommend using setScale() since it only affects the representation of the actor and causes problems with the actual dimensions within the table.
You should use a fitting width and height for your buttons and use a font with a bigger textsize.
You could use GDX Freetype to generate your fonts with the correct size on startup.
Here is an example approach for the solution:
I use the following approach for my UI elements here as an example for a Label:
This is in my static UIHelper Class:
public static Cell addToTable(Table table, Label label, float width) {
Label.LabelStyle style = new Label.LabelStyle(skin.get("default", Label.LabelStyle.class));
float aspectRatio = style.background.getMinWidth()/style.background.getMinHeight();
float height = width / aspectRatio;
style.font = Assets.font;
style.fontColor = Assets.font.getColor();
label.setStyle(style);
label.setAlignment(Align.center);
return table.add(label).width(width).height(height);
}
Then I can just call:
float width = (float)Gdx.graphics.getWidth()*0.8f; // I want my label to be 80% of the screen width
UIHelper.addToTable(table, levelLabel, width).colspan(3).pad(20);
For my fonts, I do this:
private static BitmapFont generateFont(){
FreeTypeFontGenerator generator = new FreeTypeFontGenerator(Gdx.files.internal("skins/beemelon/passion-one-regular.ttf"));
FreeTypeFontGenerator.FreeTypeFontParameter parameter = new FreeTypeFontGenerator.FreeTypeFontParameter();
parameter.size = (int) (38 * Gdx.graphics.getDensity()); // Change the 38 to a value fit for your game
parameter.color = new Color(255f / 255f, 165f / 255f, 23f / 255f, 1f); // Divide by 255f to get a value between 0 and 1
parameter.borderWidth = parameter.size / 10f;
parameter.borderColor = Color.BLACK;
BitmapFont bitmapFont = generator.generateFont(parameter);
generator.dispose();
return bitmapFont;
}
Hope this helps or pushes you in the right direction.
I am trying to draw a HUD that shows the score and time and image like loading but I want to update and change the image when the score get higher but I tried to do that but it is not working. I thought maybe I can define new table in the update method and put different image each time but I don't want to define new table each time. is there anyway to update the image only inside the table:
this is the code:
public class Hud implements Disposable{
public Stage stage;
private Viewport viewport;
private static Integer worldTimer;
private float timecount;
private static Integer score;
Label countdownLabel;
private static Label scorelabel;
private Label timelabel;
private Label levellabel;
private Label worldlabel;
private Label mariolabel;
private Image loading;
private Table table;
public Hud(SpriteBatch sb)
{
worldTimer=40;
timecount=0;
score=0;
viewport=new FitViewport(Fruits.V_WIDTH,Fruits.V_HIEGT,new OrthographicCamera());//2
stage=new Stage(viewport,sb);//stage is as box and try to put widget and organize things inside that table
table = new Table();
table.top();//table at top of our stage
table.setFillParent(true);//table is now fill all the stage
countdownLabel=new Label(String.format("%02d",worldTimer),new Label.LabelStyle(new BitmapFont(), Color.BLACK));//label for gdx
scorelabel=new Label(String.format("%02d",score),new Label.LabelStyle(new BitmapFont(), Color.BLACK));//label for gdx
timelabel=new Label("TIME",new Label.LabelStyle(new BitmapFont(), Color.BLACK));//label for gdx
levellabel=new Label("1-1",new Label.LabelStyle(new BitmapFont(), Color.BLACK));//label for gdx
worldlabel=new Label("WORLD",new Label.LabelStyle(new BitmapFont(), Color.BLACK));//label for gdx
mariolabel=new Label("Score" ,new Label.LabelStyle(new BitmapFont(), Color.BLACK));//label for gdx
loading = new Image(new Texture("10%.png"));
//loading.setSize(40, 10);
table.add(mariolabel).expandX().padTop(10);
table.add(timelabel).expandX().padTop(10);
table.add(worldlabel).expandX().padTop(10);
table.row();
table.add(scorelabel).expandX();
table.add(countdownLabel).expandX();
table.add(loading).width(50).height(10);
stage.addActor(table);
}
public void update(float dt)
{
timecount+=dt;
if (timecount>1)
{
worldTimer--;
if(worldTimer>=0) {
countdownLabel.setText(String.format("%02d", worldTimer));
loading=new Image(new Texture("90.png"));
}
timecount=0;
}
}
public static int getTime()
{
return worldTimer;
}
public static void addScore(int value)
{
score +=value;
scorelabel.setText(String.format("%02d",score));
}
public static int getScore()
{
return score;
}
#Override
public void dispose() {
stage.dispose();
}
}
You should load all the texture in your constructor instead of loading them on the fly at runtime. What you are trying to do will be easily achieved in C++ but in Java, one way to do it will be to create an array of table for the textures since that is the only thing you need to update e.g :
private Table maintable = new Table();
private Table loading10Table = new Table();
private Table loading90Table = new Table();
private Image loading10 = new Image(new Texture("10%.png"));
private Image loading90 = new Image(new Texture("90%.png"));
Add loading10 to loading10Table and loading90 to loading90Table then add mainTable and loading10Table to the stage. In the update method, assuming "loading10Table" is was inserted second in the array:
stage.getActors()[1] = loading90Table;
I'm using LibGDX buttons for touch input(previously used desktop mode and keyboard keys. So far, the button listeners work as intended, but I can't position those buttons the way I want. I tried to look through the documentation and some examples and can't figure out the problem here, but from what I've read few key things I've noticed:
buttons should be placed in a table
tables can (and should) be nested
only the main table should fill the parent.
What I want to accomplish is to have labels (tableLabs) packed at the top (as per the original Mario) and the buttons to be aligned to bottom corners (so button left would be in the bottom left corner and button right at the bottom right) with jump buttons being directly above the direction buttons without regard for the screen size, something similar to having a Java Swing border layout.
Finally, I use simple "->" , "<-" and "^" as placeholders for future button graphics.
So far The result looks like this:
public class Hud implements Disposable{
public Stage stage;
public Viewport viewport;
private Integer worldTimer;
private float timeCount;
private static Integer score;
Label countDownLabel;
static Label scoreLabel;
Label timeLabel;
Label levelLabel;
Label worldLabel;
Label marioLabel;
TextButton butL, butR, butJ;
public Hud(SpriteBatch spriteBatch){
worldTimer = 300;
timeCount = 0;
score = 0;
viewport = new FitViewport(SuperMario.WORLDWIDTH, SuperMario.WORLDHEIGHT, new OrthographicCamera());
stage = new Stage(viewport, spriteBatch);
Table mainTable = new Table();
// mainTable.top().center();
mainTable.setFillParent(true);
Table tableLabs = new Table();
tableLabs.top();//align to top
// table.setFillParent(true);//fill
countDownLabel = new Label(String.format("%03d", worldTimer), new Label.LabelStyle(new BitmapFont(), Color.WHITE));
scoreLabel = new Label(String.format("%06d", score), new Label.LabelStyle(new BitmapFont(), Color.WHITE));
timeLabel = new Label("TIME", new Label.LabelStyle(new BitmapFont(), Color.WHITE));
levelLabel = new Label("1-1", new Label.LabelStyle(new BitmapFont(), Color.WHITE));
worldLabel = new Label("WORLD", new Label.LabelStyle(new BitmapFont(), Color.WHITE));
marioLabel = new Label("MARIO", new Label.LabelStyle(new BitmapFont(), Color.WHITE));
tableLabs.add(marioLabel).expandX().padTop(10);
tableLabs.add(worldLabel).expandX().padTop(10);
tableLabs.add(timeLabel).expandX().padTop(10);
tableLabs.row();
tableLabs.add(scoreLabel).expandX().padTop(10);
tableLabs.add(levelLabel).expandX().padTop(10);
tableLabs.add(countDownLabel).expandX().padTop(10);
// stage.addActor(table);
//button setup
Table butTable = new Table();
butTable.bottom();
// table.setFillParent(true);
TextButton.TextButtonStyle tbs = new TextButton.TextButtonStyle();
tbs.font = new BitmapFont();
butR = new TextButton("b1", tbs);
butR.setText("->");
butR.setColor(Color.FIREBRICK);
butR.addListener(new ChangeListener() {
#Override
public void changed(ChangeEvent event, Actor actor) {
Gdx.app.log("B-right", "pressed");
}
});
butL = new TextButton("b2", tbs);
butL.setText("<-");
butL.setColor(Color.FIREBRICK);
butL.addListener(new ChangeListener() {
#Override
public void changed(ChangeEvent event, Actor actor) {
Gdx.app.log("B-left", "pressed");
}
});
butJ = new TextButton("b3", tbs);
butJ.setText("^");
butJ.setColor(Color.FIREBRICK);
butJ.addListener(new ChangeListener() {
#Override
public void changed(ChangeEvent event, Actor actor) {
Gdx.app.log("B-jump", "pressed");
}
});
butTable.setDebug(true);
butTable.add(butJ).expandX().padBottom(10).left().expand().padRight(10);
butTable.add(butJ).expandX().padBottom(10).right().expand().padLeft(10);
butTable.row();
butTable.add(butL).expandX().padBottom(10).left().expand().padRight(10);
butTable.add(butR).expandX().padBottom(10).right().expand().padLeft(10);
mainTable.add(tableLabs).expand();
mainTable.row();
mainTable.add(butTable).expand();
mainTable.setDebug(true);
// stage.addActor(butTable);
stage.addActor(mainTable);
Gdx.input.setInputProcessor(stage);
}
public void update(float dt){
timeCount+= dt;
if(timeCount >=1){
worldTimer--;
countDownLabel.setText(String.format("%03d", worldTimer));
timeCount--;
}
}
public static void addScore(int value){
score += value;
scoreLabel.setText(String.format("%06d", score));
}
#Override
public void dispose() {
stage.dispose();
}
}
What you're missing when setting up your table cells is the fill parameter. Calling expand on a cell like you're doing makes the cell stretch to fit, but the widget inside the cell will not get bigger unless you also call fill on the cell.
So that part near the bottom where you add the two inner tables to the main table should look like this:
mainTable.add(tableLabs).expand().fill(); //stretch the inner table to the size of the cell
mainTable.row();
mainTable.add(butTable).expand().fill(); //as above
mainTable.setDebug(true);
stage.addActor(mainTable);
From what I understand when reading other peoples code on how to make different screens. You do a main handler class sort of... And then create a new class for each screen.
The thing that confuses me is that whenever you create a new screen, you have to redefine everything that's going to be rendered, like SpriteBatch, sprites, fonts, etc. Is there any way to reuse these kind of things in all screens? I mean, if I have 10 screens, and want to be able to draw text on every screen. Is it really good programming practice to make a new BitmapFont for all 10 screen classes?
I've created an Abstract Screen class that contains all the common objects for a screen, every one of my screens extend this abstract class. And that looks like this:
public abstract class AbstractScreen implements Screen {
protected final Game game;
protected InputMultiplexer multiInputProcessor;
protected ScreenInputHandler screenInputHandler;
protected Stage uiStage;
protected Skin uiSkin;
public AbstractScreen(Game game) {
this.game = game;
this.uiStage = new Stage();
this.uiSkin = new Skin();
this.screenInputHandler = new ScreenInputHandler(game);
this.multiInputProcessor = new InputMultiplexer();
multiInputProcessor.addProcessor(uiStage);
multiInputProcessor.addProcessor(screenInputHandler);
Gdx.input.setInputProcessor(multiInputProcessor);
}
private static NinePatch processNinePatchFile(String fname) {
final Texture t = new Texture(Gdx.files.internal(fname));
final int width = t.getWidth() - 2;
final int height = t.getHeight() - 2;
return new NinePatch(new TextureRegion(t, 1, 1, width, height), 3, 3, 3, 3);
}
#Override
public void render (float delta) {
Gdx.gl.glClearColor(0.2f, 0.2f, 0.2f, 1);
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
uiStage.act(Math.min(Gdx.graphics.getDeltaTime(), 1 / 30f));
uiStage.draw();
Table.drawDebug(uiStage);
}
#Override
public void resize (int width, int height) {
}
#Override
public void show() {
}
#Override
public void hide() {
dispose();
}
#Override
public void pause() {
}
#Override
public void resume() {
}
#Override
public void dispose() {
uiStage.dispose();
uiSkin.dispose();
}
}
When I want to create a new class I just extend the abstract screen and add what I need. For example I have a basic credits screen, I just need to create the components but the abstract screen draws it:
public class CreditsScreen extends AbstractScreen {
public CreditsScreen(final Game game) {
super(game);
// Generate a 1x1 white texture and store it in the skin named "white".
Pixmap pixmap = new Pixmap(1, 1, Format.RGBA8888);
pixmap.setColor(Color.WHITE);
pixmap.fill();
uiSkin.add("white", new Texture(pixmap));
// Store the default libgdx font under the name "default".
BitmapFont buttonFont = new BitmapFont();
buttonFont.scale(scale);
uiSkin.add("default", buttonFont);
// Configure a TextButtonStyle and name it "default". Skin resources are stored by type, so this doesn't overwrite the font.
TextButtonStyle textButtonStyle = new TextButtonStyle();
textButtonStyle.up = uiSkin.newDrawable("white", Color.DARK_GRAY);
textButtonStyle.down = uiSkin.newDrawable("white", Color.DARK_GRAY);
textButtonStyle.checked = uiSkin.newDrawable("white", Color.BLUE);
textButtonStyle.over = uiSkin.newDrawable("white", Color.LIGHT_GRAY);
textButtonStyle.font = uiSkin.getFont("default");
uiSkin.add("default", textButtonStyle);
// Create a table that fills the screen. Everything else will go inside this table.
Table table = new Table();
table.setFillParent(true);
uiStage.addActor(table);
table.debug(); // turn on all debug lines (table, cell, and widget)
table.debugTable(); // turn on only table lines
// Label
BitmapFont labelFont = new BitmapFont();
labelFont.scale(scale);
LabelStyle labelStyle = new LabelStyle(labelFont, Color.BLUE);
uiSkin.add("presents", labelStyle);
final Label myName = new Label("Credits and all that stuff", uiSkin, "presents");
table.add(myName).expand().center();
}
}
I also have a single class that handles the input for all the screens, the specific purpose for this is to handle how the back button works around the different screens. And this input handler class is created in the abstract class.
public class ScreenInputHandler implements InputProcessor {
private final Game game;
public ScreenInputHandler(Game game) {
this.game = game;
}
#Override
public boolean keyDown(int keycode) {
if(keycode == Keys.BACK || keycode == Keys.BACKSPACE){
if (game.getScreen() instanceof MainMenuScreen) {
Gdx.app.exit();
}
if (game.getScreen() instanceof GameScreen) {
World.getInstance().togglePause(false);
}
if (game.getScreen() instanceof CreditsScreen) {
game.setScreen(new MainMenuScreen(game));
}
}
return false;
}
}