i have the following class that is suppose to reference a font and then draw a string to the screen once an event has occured. the class is called like this .
if (grumpface.whiteballoon.getBoundingRectangle().overlaps(spriterect)) {
((Game) Gdx.app.getApplicationListener()).setScreen(new GameOverScreen());
}
;
the class it references it this but i still cant get the font to appear any suggestiosns?
class GameOverScreen implements Screen{
private Stage stage;
// Called automatically once for init objects
#Override
public void show() {
stage = new Stage();
stage.setDebugAll(true); // Set outlines for Stage elements for easy debug
BitmapFont white = new BitmapFont(Gdx.files.internal("hazey.fnt"), false);
LabelStyle headingStyle = new LabelStyle(white, Color.BLACK);
Label gameoverstring = new Label("game ovaaaa!", headingStyle);
gameoverstring.setPosition(100, 100);
stage.addActor(gameoverstring);
}
// Called every frame so try to put no object creation in it
#Override
public void render(float delta) {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
stage.act(delta);
stage.draw();
}
The font color of your label is getting set to "black", which is the same as your background color.
Related
I'm kinda new to LibGDX.
I'm just learning the ropes.
Trying to get a basic TextButton to display at a reasonable size on screen.
Working exclusively on Android IDE (AIDE).
Using only default skins and what-not, I've tried to set width and height as well as setScale() but only the text size seems to increase on the command.
What am I doing wrong?
https://oi1161.photobucket.com/albums/q501/StudioGilliam/Screenshot_20190423-184819_LibGDXButtonsTest.jpg
public class MyGdxGame implements ApplicationListener
{
private Stage stage;
private Table table;
private TextButton btn;
#Override
public void create()
{
stage = new Stage(new ScreenViewport());
Gdx.input.setInputProcessor(stage);
table = new Table();
table.setBounds(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
TextButton.TextButtonStyle style = new TextButton.TextButtonStyle();
style.font = new BitmapFont();
btn = new TextButton("Button", style);
btn.pad(20);
btn.setTransform(true);
btn.setScale(5.0f);
btn.setTouchable(Touchable.enabled);
table.add(btn);
table.debug();
stage.addActor(table);
}
#Override
public void render()
{
Gdx.gl.glClearColor(0, 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(){}
}
EDIT:
I realised that parent objects like stages and tables control the properties of their children, so I added:
table.add(btn).width(300).height(100);
And now it looks better but the text is way off centre...
https://oi1161.photobucket.com/albums/q501/StudioGilliam/Screenshot_20190423-191104_LibGDXButtonsTest.jpg
On a Textbutton, you should use setFontScale() and pack() to resize the button to the font size.
However, for supporting different screen sizes without any own coding, consider using FitViewport/ExtendViewport
I am trying to make an object that extends the Actor class. but whenever I have call the Stage's draw() method, it only draws the button I added to it. Here is my code, maybe someone here can help me?
Code for my Screen class (Assume that I had overridden all necessary methods and that I imported all necessary classes):
public class PlayScreen implements Screen{
SpriteBatch batch;
Game game;
Table table;
Skin skin;
Stage stage;
BitmapFont font;
TextButton button;
TextDisplay display;
public PlayScreen(MyGdxGame game, SpriteBatch batch){
this.game = game;
this.batch = batch;
//instantiating Stage, Table, BitmapFont, and Skin objects.
font = new BitmapFont(Gdx.files.internal("MyTruefont.fnt"));
table = new Table();
stage = new Stage();
skin = new Skin(Gdx.files.internal("Test.json"));
button = new TextButton("Start!", skin, "default");
display = new TextDisplay(font, this);
//Setting table properties
table.setWidth(stage.getWidth());
table.align(Align.center|Align.top);
table.setPosition(0, Gdx.graphics.getHeight());
table.padTop(30);
//Adding actors to table
table.add(button).padBottom(50);
table.add(display);
//Adding table to stage and setting stage as the input processor
stage.addActor(table);
Gdx.input.setInputProcessor(stage);
}
#Override
public void show() {
}
#Override
public void render(float delta) {
Gdx.gl.glClearColor(1, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
stage.draw();
batch.end();
}
And here is My Textdisplay class that extends Actor (Again assume all other methods have been overriden, and all necessary classes have been imported):
public class TextDisplay extends Actor implements Drawable {
Texture texture;
BitmapFont font;
String str;
public TextDisplay(BitmapFont font, Screen screen){
this.font = font;
texture = new Texture(Gdx.files.internal("TextArea.png"));
str = "";
setLeftWidth(texture.getWidth());
setRightWidth(texture.getWidth());
setBottomHeight(texture.getHeight());
setTopHeight(texture.getHeight());
}
#Override
public void draw(Batch batch, float x, float y, float width, float height) {
batch.draw(texture, x, y);
}
You overrode the wrong draw method. Actor's draw method signature is:
public void draw (Batch batch, float parentAlpha)
You overrode the one from Drawable. Not sure why you're implementing Drawable. There's already an Actor available for drawing text anyway, called Label.
Also, if you want to put your Actor in a table, you need to set its width and height, or the width and height of its cell in the table.
I'm trying to get a screenshot to display on the background of a pause menu.
My screenshot method uses ScreenUtils.getFrameBufferPixmap() to get the screenshot; I got it from here.
My code for the pause screen is as follows:
public class CEscapeScreen implements CScreen {
private final Stage stage;
private class BGActor extends Actor {
Pixmap pixmap = CUtil.getScreenshot(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), false);
Texture t = new Texture(pixmap);
#Override
public void draw(Batch batch, float alpha) {
batch.draw(t, 0, 0);
}
}
public CEscapeScreen(CGame g) {
Actor bgActor = new BGActor();
stage = new Stage();
final TextButton quitButton = new TextButton("Quit to Main Menu", CUi.getUISkin(), "default");
...
table.add(quitButton);
stage.addActor(bgActor);
stage.addActor(table);
}
#Override
public void display() {
stage.draw();
}
}
The display method is called every frame by the current Screen the program is on.
What I'm trying to accomplish is to get a screenshot of the screen before the pause screen stage is drawn, and then draw that screenshot behind the quitButton.
Every other Screen clears and makes a new Stage like this one.
The problem I'm having, is that only the quitButton appears on the Escape Menu. Why does this happen?
I'm new to LibGDX and I am taking it slowly. I'm still trying to understand most things which is why typically google searches don't help due to the fact that their too complicated. I have a main menu that has text that I want centered no matter what the screen size is. Here is the code that I have for that menu.
public class Menu implements Screen {
SlingshotSteve game;
OrthographicCamera camera;
public Menu(final SlingshotSteve gam) {
this.game = gam;
camera = new OrthographicCamera();
camera.setToOrtho(false, 800, 480);
}
#Override
public void render(float delta) {
Gdx.gl.glClearColor(0, 0, 0.2f, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
camera.update();
game.batch.setProjectionMatrix(camera.combined);
game.batch.begin();
game.font.draw(game.batch, "Welcome to Slingshot Steve!!! ", 100, 150);
game.font.draw(game.batch, "Tap anywhere to begin!", 100, 100);
game.batch.end();
if (Gdx.input.isTouched()) {
game.setScreen((Screen) new GameScreen(game));
dispose();
}
}
#Override
public void resize(int width, int height) {
}
#Override
public void show() {
}
#Override
public void hide() {
}
#Override
public void pause() {
}
#Override
public void resume() {
}
#Override
public void dispose() {
}
}
I'm here to save you!
To get width / height from a String drawn with your BitmapFont you can utilize this super nice method:
game.font.getBounds(String string)
And to use it in your case, it would be something like this:
game.font.getBounds("Tap anywhere to begin!").width / 2;
Cheers!
It is possible to do it the way Nine Magics suggested, however one would usually do it via a Stage, which is part of scene2d.
More specifically one would use scene2d.ui which is a bunch of Actors like Button, Image, Label etc. You can attach a ClickListener to a Button for example and react on this event.
Furthermore, for layouting there is one very powerful Actor, namely Table which you can very easily use to center things on the screen.
Some very minimalistic code:
// do this once, in create() or show()
Skin skin = new Skin("uiskin.json"); // get the demo skin from the libgdx test resources
Stage stage = new Stage();
Table table = new Table(skin);
table.add("Welcome to Slingshot Steve!!!");
table.row();
table.add("Tap anywhere to begin!");
stage.addActor(table);
// do this in your render loop
stage.act();
stage.draw();
You can find the "default" skin resources here. You need to get all the uiskin.* files.
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;
}
}