LibGDX: Skin and scaling problems - libgdx

I'm trying to use Skins with TextButtons. However I'm having an issue where the TextureRegions of the Skin are NOT being scaled down to the tablesize.
This is leading to an issue like in this image:
As you can see that is the e from the word Hello. I managed to scale that down to a more reasonable size (still wrong). However the Button textures are still way too large.
Any ideas? Because I am pulling my hair out. I am using a custom viewport with a custom screenspace width and height. Here is the create method for the menu.
public void create(){
menuStage = new Stage();
camera = new OrthographicCamera();
viewPort = new StretchViewport(SCREEN_SPACE_WIDTH, SCREEN_SPACE_HEIGHT, camera);
viewPort.setWorldSize(SCREEN_SPACE_WIDTH, SCREEN_SPACE_HEIGHT);
menuStage.setViewport(viewPort);
devTexture = new Sprite (new Texture(Gdx.files.internal("data/16by9.png"), true));
Image newActor = new Image(devTexture.getTexture());
newActor.setSize(
viewPort.getWorldWidth(),
viewPort.getWorldHeight()
);
menuStage.addActor(newActor);
skin = new Skin(Gdx.files.internal("data/uiskin.json"));
menuTable = new Table();
skin.getFont("default-font").setScale(0.08f);
menuTable.debugAll();
menuTable.setFillParent(true);
TextButton a,b,c;
a = new TextButton("hello", skin);
b = new TextButton("hello", skin);
c = new TextButton("hello", skin);
a.getStyle().up.setMinWidth(2.0f);
b.getStyle().up.setMinHeight(2.0f);
b.getStyle().up.setMinWidth(2.0f);
c.getStyle().up.setMinHeight(2.0f);
c.getStyle().up.setMinWidth(2.0f);
menuTable.row();
menuTable.add(a).size(2.0f, 1.0f);
menuTable.add(b).size(2.0f, 1.0f);
menuTable.add(c).size(2.0f, 1.0f);
menuStage.addActor(menuTable);
camera.translate(
newActor.getWidth() / 2,
newActor.getHeight() / 2
);
}

Related

Libgdx font cut

I have an issue with libgdx BitMapFont, I display labels inside of a scene2d table, but the font is "cut" at some parts of the text (see below).
Here is my code :
For declaring the font :
font12 = new BitmapFont(Gdx.files.internal("fonts/text.fnt"));
font12.setUseIntegerPositions(false);
font12.getData().setScale(0.2f);
For declaring the table :
Table table = new Table();
table.top();
table.setFillParent(true);
LabelStyle lblStyle = new LabelStyle();
lblStyle.font = font12;
scoreLabel =new Label("SCORE", lblStyle);
timeLabel = new Label("TIME", lblStyle);
levelLabel = new Label("LEVEL", lblStyle);
Thank you for your help.
[EDIT]
Here is the code I tried using freetype but this doesn't look smooth :
FreeTypeFontGenerator generator = new FreeTypeFontGenerator(Gdx.files.internal("fonts/OpenSans-Regular.ttf"));
FreeTypeFontParameter parameter = new FreeTypeFontParameter();
parameter.size = 18;
parameter.color = Color.BLACK;
generator.scaleForPixelHeight(18);
parameter.minFilter = Texture.TextureFilter.Linear;
parameter.magFilter = Texture.TextureFilter.Linear;
parameter.mono = false;
parameter.gamma = 2f;
font12 = generator.generateFont(parameter); // font size 12 pixels
font12.setUseIntegerPositions(false);
font12.getRegion().getTexture().setFilter(TextureFilter.Linear, TextureFilter.Linear);
generator.dispose(); // don't forget to dispose to avoid memory leaks!
First thing, you should always avoid scaling fonts because the result is pixelated and looks really bad. You can generator fonts to the correct size that you need within your program using the FreeTypeFontGenerator:
https://github.com/libgdx/libgdx/wiki/Gdx-freetype
When adding components to a table the table sets the size on its child components. Essentially, the table will override the size of the label when the label is added to the table.
To make sure the label keeps the same size, set the size on the table's cell that is holding the label like this:
table.add(label).size(label.getWidth(), label.getHeight());
You can also apply a different size to the label when adding it to the table (if for example you wanted to have extra space around the label):
table.add(label).size(500, 100);
EDIT
This code works for me, give this a try.
private Stage stage;
#Override
public void create () {
stage = new Stage();
stage.setViewport(new ScreenViewport(stage.getViewport().getCamera()));
Table table = new Table();
table.setFillParent(true);
stage.addActor(table);
FreeTypeFontGenerator gen = new FreeTypeFontGenerator(Gdx.files.internal("internal/arialbd.ttf"));
FreeTypeFontGenerator.FreeTypeFontParameter param = new FreeTypeFontGenerator.FreeTypeFontParameter();
param.size = 18;
param.borderColor = new Color(Color.BLACK);
param.borderWidth = 1;
BitmapFont font = gen.generateFont(param);
gen.dispose();
Label.LabelStyle style = new Label.LabelStyle();
style.font = font;
Label label = new Label("Hello World", style);
table.add(label).size(label.getWidth(), label.getHeight());
}
#Override
public void render() {
Gdx.gl.glClearColor(0.6f, 0.8f, 0.8f, 1.0f);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
stage.act(Gdx.graphics.getDeltaTime());
stage.draw();
}
#Override
public void resize(int width, int height) {
stage.getViewport().update(width, height, true);
}

Screen Display not proper on some screens Libgdx

I am developing a game in which i am making a Game Over Screen but the components are not rearranging properly.
What i am Getting on 1024 * 720 screen is:
and what it should look like:
and the code is:
#Override
public void show() {
stage = new Stage(new ScreenViewport());
camera = new OrthographicCamera(Gdx.graphics.getWidth(),Gdx.graphics.getHeight());
Gdx.input.setInputProcessor(stage);
font = new BitmapFont(Gdx.files.internal("newfont.fnt"));
verysmallfont = new BitmapFont(Gdx.files.internal("verysmallfont.fnt"));
smallfont = new BitmapFont(Gdx.files.internal("smallfont.fnt"));
atlas = new TextureAtlas("ui/buttons.pack");//add atlas
skin = new Skin(atlas);
table = new Table(skin);
actiontable = new Table(skin);
actionbar = new Table(skin);
actionbar2 = new Table(skin);
table.setBounds(0,0,Gdx.graphics.getWidth(),Gdx.graphics.getHeight());
actiontable.setBounds(0,0,Gdx.graphics.getWidth(),Gdx.graphics.getHeight());
actionbar.setBounds(0,0,Gdx.graphics.getWidth(),Gdx.graphics.getHeight());
actionbar2.setBounds(0,0,Gdx.graphics.getWidth(),Gdx.graphics.getHeight());
TextButton.TextButtonStyle buttonback = new TextButton.TextButtonStyle();
buttonback.up = skin.getDrawable("back");
buttonback.pressedOffsetX = 1;
buttonback.pressedOffsetY = -1;
buttonback.font = font;
buttonBack = new TextButton("",buttonback);
TextButton.TextButtonStyle lifebuttonstyle = new TextButton.TextButtonStyle();
lifebuttonstyle.up = skin.getDrawable("life");
lifebuttonstyle.pressedOffsetX = 1;
lifebuttonstyle.pressedOffsetY = -1;
lifebuttonstyle.font = font;
buttonlife = new TextButton("",lifebuttonstyle);
TextButton.TextButtonStyle textButtonStyle = new TextButton.TextButtonStyle();
textButtonStyle.up = skin.getDrawable("heart_game_continue");
textButtonStyle.pressedOffsetX = 1;
textButtonStyle.pressedOffsetY = -1;
textButtonStyle.font = font;
buttonPlay = new TextButton("",textButtonStyle);
TextButton.TextButtonStyle adsfreeStyle = new TextButton.TextButtonStyle();
adsfreeStyle.up = skin.getDrawable("Video");
adsfreeStyle.pressedOffsetX = 1;
adsfreeStyle.pressedOffsetY = -1;
adsfreeStyle.font = font;
buttonVideo = new TextButton("",adsfreeStyle);
TextButton.TextButtonStyle sharebuttonStyle = new TextButton.TextButtonStyle();
sharebuttonStyle.up = skin.getDrawable("Replay");
sharebuttonStyle.pressedOffsetX = 1;
sharebuttonStyle.pressedOffsetY = -1;
sharebuttonStyle.font = font;
buttonReplay = new TextButton("",sharebuttonStyle);
Label.LabelStyle headingstyle = new Label.LabelStyle(font,Color.WHITE);
label = new Label("Game Over",headingstyle);
label.setFontScale(1.7f);
Label.LabelStyle contstyle = new Label.LabelStyle(smallfont,Color.WHITE);
cont = new Label("Continue?",contstyle);
cont.setFontScale(2f);
Label.LabelStyle replaystyle = new Label.LabelStyle(verysmallfont,Color.WHITE);
replay = new Label("Replay",replaystyle);
shortVideo = new Label("(Short Video)",replaystyle);
replay.setFontScale(2f);
shortVideo.setFontScale(2f);
table.align(Align.top);
table.padTop(197f);
table.add(label);
table.getCell(label).spaceBottom(150f);
table.row();
table.add(cont);
table.getCell(cont).spaceBottom(80f);
table.row();
table.add(buttonPlay).size(200f,200f);
actiontable.add(buttonVideo).size(200f,200f);
actiontable.add(buttonReplay).size(200f,200f);
actiontable.align(Align.bottom);
actiontable.getCell(buttonVideo).spaceBottom(20f).padRight(100f);
actiontable.getCell(buttonReplay).spaceBottom(20f).padLeft(100f);
actiontable.row();
actiontable.add(shortVideo).padRight(100f);
actiontable.add(replay).padLeft(100f);
actiontable.padBottom(197f);
actiontable.setFillParent(true);
actionbar.align(Align.topLeft).setWidth(Gdx.graphics.getWidth());
actionbar.add(buttonBack).align(Align.left).size(90f,90f);
actionbar2.align(Align.topRight);
actionbar2.add(buttonlife).align(Align.right).size(90f,90f);
actionbar.getCell(buttonBack).pad(43f);
actionbar2.getCell(buttonlife).align(Align.right).pad(43f);
stage.addActor(actionbar2);
stage.addActor(actionbar);
stage.addActor(table);
stage.addActor(actiontable);
buttonPlay.addListener(new ClickListener(){
#Override
public void clicked(InputEvent event, float x, float y) {
((Game) Gdx.app.getApplicationListener()).setScreen(new Main(level,a,start,sweep,collide,innerarcs,out,mid,arcsleft,left,pointerColor));
};
});
buttonReplay.addListener(new ClickListener(){
#Override
public void clicked(InputEvent event, float x, float y) {
int total = out+mid+innerarcs;
((Game) Gdx.app.getApplicationListener()).setScreen(new Main(level,a,total,pointerColor));
}
});
buttonBack.addListener(new ClickListener(){
#Override
public void clicked(InputEvent event, float x, float y) {
((Game) Gdx.app.getApplicationListener()).setScreen(new Menu(level));
}
});
}
SpriteBatch batch;
#Override
public void render(float delta) {
Gdx.gl.glClearColor(0.184f,0.184f,0.184f,1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
stage.act(delta);
stage.draw();
}
private OrthographicCamera camera;
#Override
public void resize(final int width, final int height) {
table.setTransform(true);
table.setSize(width,height);
actiontable.setTransform(true);
actiontable.setSize(width,height);
actionbar.setTransform(true);
actionbar.setSize(width,height);
}
I am new to libgdx please help i dont have any knowledge about how to use camera and viewports.
Thanks in advance..
€dit: sorry my bad - there's nothing like "stage.resize"
But I'll let the answer in, because it'll fix your problem, though not as fast as you wish, but in a more clear way.
(THE FOLLOWING TEXT IS NOT NECESSARRY FOR THE ANWSER AND ARE ONLY SUGGESTIONS)
(if you follow the following steps, you'll save yourself time & headaches in the future)
I'd suggest a viewport, because they'll kill many problems with scaling, and there are quite a few, from which you can choose, as you need.
LibGdx Viewports
A viewport takes care for different screen sizes with the help from different techniques (e.g. scaling, black bars)
Additionally a viewport is SUPER easy to implement.
You'll do the following(e.g. FitViewport(stretches content, if necessary)):
stage = new Stage();
OrthographicCamera cam = new OrthographicCamera();
cam.setToOrtho(false, 800, 600);
stage.setViewport(new FitViewport(800, 600, cam));
TADA. You implemented a viewport. Was not so hard.
(but make sure to call stage.getViewport().update(w, h) in the resize(w, h) method!! AND DON'T FORGET IT!!)
Second suggestion I'd do is:
Use a main table.
So you do following
Table myMothershipTable = new Table();
myMothershipTable.setFillParent(true);
myMothershipTable.add(add);
myMothershipTable.add(all);
myMothershipTable.add(content);
stage.addActor(myMothershipTable);
Now you've only one actor, which is the table, and you can be damned sure, that this table will fill the whole screen.
Your screen is 10999x3? yeah. the table will be 10999x3.
Good. If you've refactored your whole stuff into one table I'd suggest the next step:
stage.setDebugAll(true); //this will help you to see the actual buildup from your actors & elements
So heres the why:
The viewport takes care for your stage size
the single table makes sure, that your complete content will be within the screen ==> now you can add one item after another, and make sure with..
stage.setDebugAll(true).. that your content is placed properly.
If you follow this simple steps, you'll save yourself a lot of time and headache with designing the UI.

Sprite is not attached with a body in libgdx

I want the sprite to get attached with a polygon shape body. When I run the code, both the sprite and body is getting displayed but they are not linked with each other. I looked at all the stack overflow questions but nothing helped.
I am creating this in a class and I am instantiating this from main class.
This is my code,
public SpriteButtons(PlayScreen screen) {
this.world = screen.getWorld();
batch = new SpriteBatch();
region = new TextureRegion(screen.getAtlas().findRegion("fireball"), 0, 0, 16, 16);
sprite = new Sprite(region);
this.gamecame = new OrthographicCamera();
BodyDef bodyDef = new BodyDef();
bodyDef.type = BodyDef.BodyType.StaticBody;
bodyDef.position.set(0, 0);
body = world.createBody(bodyDef);
PolygonShape shape = new PolygonShape();
shape.setAsBox(0.2f, 0.2f);
FixtureDef fixtureDef = new FixtureDef();
fixtureDef.shape = shape;
fixtureDef.density = 1f;
sprite.setSize(25, 25);
Fixture fixture = body.createFixture(fixtureDef);
}
public OrthographicCamera getGamecame() {
return gamecame;
}
public void render(float dt) {
sprite.setPosition(body.getPosition().x - sprite.getWidth()/2f,
body.getPosition().y - sprite.getHeight()/2f );
Gdx.app.log("" + body.getPosition().x, "");
batch.begin();
sprite.draw(batch);
setRegion(region);
batch.end();
}
My output is as follows,
The badlogic sprite is not getting attached with a polygon body and I am instantiating this class from main class and I will be calling this class render method from main class render method. Sorry if the question seems stupid. I don't know where I am missing this. Please help..!! Thanks in advance..!!
You must update sprite's position according to the body position in the render method - if you are not doing this how the sprite can know that it is attached to body?
Please notice that box2d body's origin is in the center of the body when libgdx'es sprite's origin is at it's left botto corner. Then you need to subtract half of width and height of body's position.
So this is what you've got to do:
//render()
sprite.setPosition(body.getPosition().x - sprite.getWidth()/2f,
body.getPosition().y - sprite.getHeight()/2f );
...
sprite.draw(batch);
...
try doing this
batch.draw(sprite, sprite.getX(), sprite.getY()); and change body's inital postion somewher above,so that it fall and you can check under gravity by initializing world like world = new World(new Vector2(0, -98f), true);

How to re-size a TextButton accordingly to the Stage size using Libgdx

As you can see in my code below, I create a camera using the width and height of the device target. Then I create stage with the size of the camera viewport and add a Window to it (everything works fine till here in any device).
However, when add a TextButton to the Windows is not re-sized accordingly to the Stage size.
So, how can I re-size a TextButton to looks good in any device?
#Override
public void create() {
.
.
.
// Define camera our view port in meters because of Box2D
camera = new OrthographicCamera(20,
20 * (Gdx.graphics.getHeight() / (float) Gdx.graphics.getWidth()));
// create stage with the size of the viewport
stage = new Stage(new StretchViewport(camera.viewportWidth,camera.viewportHeight));
// create restart button
atlas = new TextureAtlas("data/ui/atlas.pack");
skin = new Skin(Gdx.files.internal("data/ui/menu_skin.json"), atlas);
TextButton restartButton = Util.createTextButton("Restart", skin, "red",
new ClickListener() {
#Override
public void clicked(InputEvent event, float x, float y) {
timer=timeMax;
}
});
// create a window and add the restart to it
skin.add("texture", new Texture("data/texture.png"));
WindowStyle windowStyle = new WindowStyle(new BitmapFont(), Color.WHITE, skin.newDrawable("texture"));
windowTryAgain = new Window("", windowStyle);
windowTryAgain.setMovable(false);
//windowTryAgain.padTop(20);
//stage.addActor(window);
windowTryAgain.setPosition(0, 0);
windowTryAgain.setSize(2,2);
windowTryAgain.row().fill().expandX();
windowTryAgain.add(restartButton).fill(0f, 0f);
windowTryAgain.center();
windowTryAgain.setVisible(false);
stage.addActor(windowTryAgain);
.
.
.
}
public class Util {
public static TextButton createTextButton(String text, Skin skin,
String styleName, EventListener listener) {
TextButton textButton = new TextButton(text, skin, styleName);
textButton.pad(10);
//Set height does not work in my case
//textButton.setHeight(0.1f);
textButton.addListener(listener);
return textButton;
}
}
You can make a secondary camera and attach it to your stage. To scale the table just scale the viewport size of the secondary camera
An example would be:
//Heres where you set the scale of your buttons and your table
Camera secondaryCamera = new Camera(Gdx.graphics.getWidth() * scale,
Gdx.graphics.getHeight() * scale);
Stage stage = new Stage();
Table table = new Table();
ImageButton button = new ImageButton(drawableUp, drawableDown, drawableChecked);
table.setFillParent(true);
stage.getViewport().setCamera(secondaryCamera);
table.add(ImageButton);
stage.addActor(table);
This works great when your using it for touch controls. You can use a table for the entire UI and scale it to your liking independent of your other game items;

JPanels won't show in GridBagLayout

When I add a JPanel(1) into my GridBagLayout JPanel(2), my JPanel(1) is shrinked into a tiny square located in the middle. I don't know why this happened, because in theory it should work. I think it might have something to do with default BorderLayout? cause I read somewhere that BorderLayout puts your JPanel in the middle. But I have already set my Layout as GridBag, so I don't know why this is happening. Here's my code:
JFrame f = new JFrame("TEST");
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
f.setSize(300, screenSize.height);
f.setLocation(screenSize.width - 300, 0);
f.setVisible(true);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
GridBagConstraints gbc = new GridBagConstraints();
JPanel panel = new JPanel(new GridBagLayout());
JPanel A = new JPanel();
Dimension d = new Dimension(270, 50);
A.setSize(d);
A.setBackground(Color.GREEN);
JPanel B = new JPanel();
B.setSize(d);
B.setBackground(Color.BLUE);
gbc.gridy = 0;
panel.add(A, gbc);
gbc.gridx = 1;
panel.add(B, gbc);
f.add(panel);
f.validate();
f.repaint();
More over, when I set the border for A and B to 100 pixels, both of them start showing up. So I am really confused!
Stop pulling your hair with GridBagLayout, try MigLayout instead, you'll save a lot of time:
http://www.miglayout.com