i am trying to code a HUD for my game but i cannot figure out how to scale a Label properly I am using this code:
Label hpLabel = new Label("HP: ",new Label.LabelStyle(new BitmapFont(),Color.BROWN));
table.add(hpLabel);
viewport = new FitViewport(Gdx.graphics.getWidth()/ FacultyWars.PPM, Gdx.graphics.getHeight()/ FacultyWars.PPM, cam);
stage = new Stage(viewport, batch);
stage.addActor(table);
//other ellements added after this
The HP tag is enormous on the screen. I tried using setScale on the label and on the table to no avail. Any help is appreciated!
Thanks
Here is a picture of the current screen https://gyazo.com/57c190a9d7516bb8b2256bf1a7d17b4c
Simply add the Label to a Group then apply the scale to the group.
Label label = new Label("hello", skin);
Group group = new Group();
group.addActor(label);
group.setScale(2f, 2f);
I only scale Groups with Labels in animations where at the end of the animation the scale is 1. One should not scale fonts, because it looks pixelated. For example, a simple scale up scale down animation:
group.addAction(Actions.sequence(Actions.scaleTo(2f, 2f, 1f), Actions.scaleTo(1f, 1f, 1f)));
Use setFontScale(float fontScale) method of Label
Related
I am new to the libgdx framework trying to make a game but the problem here is I don't know how to scale the ImageButton for different screen sizes it looks big on desktop but looking small on the android devices. I am using several ImageButtons of different sizes and using table to organize them. Can anyone please make some code changes so I could understand how to scale the images here with the viewports?
public class BabyPhone extends Game {
public static final int WIDTH = 480;
public static final int HEIGHT = 800;
public void create () {
bg = new BabyActor();
bg.setTexture(new Texture("background-orange.png"));
bg.setSize(Gdx.graphics.getWidth(),Gdx.graphics.getHeight());
phone = new BabyActor();
phone.setTexture(new Texture("blue-phone.png"));
phone.setSize(Gdx.graphics.getWidth(),Gdx.graphics.getHeight());
TextureRegion btLeft = new TextureRegion(new Texture("10OFF.png"));
Drawable drawableLeft = new TextureRegionDrawable(new TextureRegion(btLeft));
buttonLeft = new ImageButton(drawableLeft);
TextureRegion btRight = new TextureRegion(new Texture("12OFF.png"));
Drawable drawableRight = new TextureRegionDrawable(new TextureRegion(btRight));
buttonRight = new ImageButton(drawableRight);
TextureRegion btCenter = new TextureRegion(new Texture("11OFF.png"));
Drawable drawableCenter = new TextureRegionDrawable(new TextureRegion(btCenter));
buttonCenter = new ImageButton(drawableCenter);
TextureRegion bt1 = new TextureRegion(new Texture("1OFF.png"));
Drawable drawable = new TextureRegionDrawable(new TextureRegion(bt1));
button1 = new ImageButton(drawable);
TextureRegion bt2 = new TextureRegion(new Texture("2OFF.png"));
Drawable drawable1 = new TextureRegionDrawable(new TextureRegion(bt2));
button2 = new ImageButton(drawable1);
TextureRegion bt3 = new TextureRegion(new Texture("3OFF.png"));
Drawable drawable2 = new TextureRegionDrawable(new TextureRegion(bt3));
button3 = new ImageButton(drawable2);
TextureRegion bt4 = new TextureRegion(new Texture("4OFF.png"));
Drawable drawable3 = new TextureRegionDrawable(new TextureRegion(bt4));
button4 = new ImageButton(drawable3);
TextureRegion bt5 = new TextureRegion(new Texture("5OFF.png"));
Drawable drawable4 = new TextureRegionDrawable(new TextureRegion(bt5));
button5 = new ImageButton(drawable4);
TextureRegion bt6 = new TextureRegion(new Texture("6OFF.png"));
Drawable drawable5 = new TextureRegionDrawable(new TextureRegion(bt6));
button6 = new ImageButton(drawable5);
TextureRegion bt7 = new TextureRegion(new Texture("7OFF.png"));
Drawable drawable6 = new TextureRegionDrawable(new TextureRegion(bt7));
button7 = new ImageButton(drawable6);
TextureRegion bt8 = new TextureRegion(new Texture("8OFF.png"));
Drawable drawable7 = new TextureRegionDrawable(new TextureRegion(bt8));
button8 = new ImageButton(drawable7);
TextureRegion bt9 = new TextureRegion(new Texture("9OFF.png"));
Drawable drawable8 = new TextureRegionDrawable(new TextureRegion(bt9));
button9 = new ImageButton(drawable8);
gamecam = new OrthographicCamera(WIDTH,HEIGHT);
gamecam.position.set(WIDTH/2,HEIGHT/2,0);
gamePort = new ScreenViewport(gamecam);
backStage = new Stage(gamePort);
fitPort = new FitViewport(gamecam.viewportWidth,gamecam.viewportHeight,gamecam);
frontStage = new Stage(fitPort);
backStage.addActor(bg);
frontStage.addActor(phone);
Table table = new Table();
table.padLeft(40);
table.setPosition(phone.getWidth()/2,phone.getHeight()/2*0.6f);
table.row().size(95,95);
table.add(buttonLeft);
table.add(buttonCenter);
table.add(buttonRight);
table.row().size(95,95);
table.add(button1);
table.add(button2);
table.add(button3);
table.row().size(95,95);
table.add(button4);
table.add(button5);
table.add(button6);
table.row().size(95,95);
table.add(button7);
table.add(button8);
table.add(button9);
frontStage.addActor(table);
}
public void render(){
backStage.act(Gdx.graphics.getDeltaTime());
frontStage.act(Gdx.graphics.getDeltaTime());
backStage.draw();
frontStage.draw();
}
#Override
public void resize(int width, int height) {
gamePort.update(width, height);
frontStage.getViewport().update(width, height);
}
I'm just setting it as a percentage of a device size. It's loks like this.
float BUTTON_SIZE = 0.1f;
table.add(button2).size(Gdx.graphics.getWidth()*BUTTON_SIZE,Gdx.graphics.getWidth()*BUTTON_SIZE);
If you want to use a Viewport you must choose which Viewport you will use.
ScreenViewport
The ScreenViewport will always fill the whole Screen and will stretch your Textures etc. to the Fullscreen.
FitViewport
The FitViewport will not stretch your Textures it will look that the ratio between width and height will always be the same. This Viewport will produce Sidebars on the sides if the Screen doesn't match the defined ratio. So the shorter side will match the screen.
FillViewport
The FillViewport will not stretch your Textures it will look that the ratio between width and height will always be the same. This Viewport does not create Sidebars like FitViewport because it will match the longer side to the screen. So it can happen that something is cut off.
More Viewports: https://github.com/libgdx/libgdx/wiki/Viewports
In my Example, I will use FitViewport.
To use a FitViewport we must create a Camera. We create an OrthographicCamera. With this Camera, we can define the Virtual width and height of our Viewport so the width and height of what we can see.
Camera camera = new OrthographicCamera(100,100);
Now it's important that you think in this virtual size we defined and not in pixels. So we have a size of 100 x 100 units.
Now let's create our FitViewport with our Camera:
FitViewport viewport = new FitViewport(camera.viewportWidth, camera.viewportHeight, camera);
And finally create our Stage with the Viewport:
Stage stage = new Stage(viewport);
So if we now add our buttons to the table we can define the Size of the Buttons in our Virtual size.
So if we add our Button like this:
table.add(button1).size(10,10);
The Button will always be 10% of the Screen because the Button is 10 units big in a world of 100 units
The advantage now of FitViewport is: we defined the Button to be 10x10 so a Ratio of 1:1, a square. If we now resize the Screen or have a different Screen size the Button will always be a square and will always fill 10 of 100 units of the Screen.
This will maybe be a little bit confusing with Virtual size. If you will read more about it, here is a little bit better description: How Camera works in Libgdx and together with Viewport
One more thing we must do before the Viewport works perfectly.
We must update the Viewport in the resize method:
#Override
public void resize(int width, int height) {
viewport.update(width, height);
}
I hope this will help you to work with Viewports.
You have written that you are new to LibGdx so I will give you some additional suggestions.
This won't work:
Gdx.input.setInputProcessor(stage);
Gdx.input.setInputProcessor(stage1);
Gdx.input can only hold one InputProcessor per time so stage1 will override stage. If you will use more than one InputProcessor use InputMultiplexer: https://github.com/libgdx/libgdx/wiki/Event-handling
If you use a Table and every actor in a row have for example the same size. Instead of writing by every actor: table.add(button1).size(10,10);
Table has a special feature, if you set something to row() this will apply to all Actors in this row.
So instead of writing this:
table.add(button1).size(10,10);
table.add(button2).size(10,10);
table.add(button3).size(10,10);
table.row();
table.add(button4).size(10,10);
table.add(button5).size(10,10);
table.add(button6).size(10,10);
You can write this:
table.row().size(10,10);
table.add(button1);
table.add(button2);
table.add(button3);
table.row().size(10,10);
table.add(button4);
table.add(button5);
table.add(button6);
I hope these little suggestions will help you.
I have a group which contains a rectangle and an image on top. I want the rectangle to be re-sizable and the image should have a fixed size except for the case when the rectangle is smaller than the image. Then the image should down-size with the rectangle.
The image should also always be centered and have some padding.
I have most of these parts done, except the down-sizing part of the image. I don't know why, but the image will not down-size at all. This is what I've got.
Group group = new Group()
GeometryNode<Rectangle> rectangle = new GeometryNode<>();
rectangle.setGeometry(new Rectangle(0, 0, 60, 60));
ImageView imageView = new ImageView(image);
imageView.setPreserveRatio(true);
ImageViewPane imagePane = new ImageViewPane(imageView);
imagePane.setMinSize(0, 0);
imagePane.setMaxSize(50, 50);
StackPane stackPane = new StackPane();
stackPane.getChildren().add(rectangle);
stackPane.getChildren().add(imagePane);
group.getChildren().add(stackPane);
You want the fitWidth and fitHeight properties of the ImageView to change if the dimensions of the StackPane change. So you can do
double padding = ... ;
imageView.setPreserveRatio(true);
imageView.fitWidthProperty().bind(
Bindings.min(stackPane.widthProperty().subtract(padding), image.widthProperty()));
imageView.fitHeightProperty().bind(
Bindings.min(stackPane.heightProperty().subtract(padding), image.heightProperty()));
I am drawing a slider with Libgdx using the following code:
Pixmap pix = new Pixmap(200, 50, Pixmap.Format.RGBA8888);
pix.setColor(Color.BLACK);
pix.fill();
skin.add("sliderBackS", new Texture(pix));
Pixmap pix1 = new Pixmap(10, 70, Pixmap.Format.RGBA8888);
pix1.setColor(Color.RED);
pix1.fill();
skin.add("knobS", new Texture(pix1));
Slider.SliderStyle sliderStyle = new Slider.SliderStyle();
sliderStyle.disabledBackground = skin.newDrawable("sliderBackS");
sliderStyle.disabledKnob = skin.newDrawable("knobS");
sliderStyle.background = skin.newDrawable("sliderBackS");
sliderStyle.knob = skin.newDrawable("knobS");
skin.add("sunSlider", sliderStyle);
sunlightSlider = new Slider(0, 100, 1, false, sliderStyle);
stage.addActor(sunlightSlider);
sunlightSlider.setBounds(300, 300, 100, 10);
sunlightSlider.setDisabled(true);
sunlightSlider.setDebug(true);
And then else where:
stage.act(Math.min(Gdx.graphics.getDeltaTime(), 1 / 30f));
stage.draw();
But for some reason the pixmaps in the slider seem to be drawn at their actual size. This can be seen in the following picture (the green line is what it should be, from the debug):
For some reason the width seems to be constrained by sunlightSlider.setBounds(300, 300, 100, 10); but the height does not.
I know that I could choose the pixmap size to what ever I need, but I want to use an image from file. If I use a big image, then it overflows the bounds similarly.
I want it to look like it is above, but constrained to the green rectangle.
What am I doing wrong?
A TextureRegionDrawable, which is what you've created with your newDrawable calls, by default has a minimum size that matches its original pixel dimensions. The minimum size of the Drawable prevents the Slider widget from drawing it as small as it would like to fit it into its own bounds. So you can reduce the minimum size:
sliderStyle.disabledBackground = skin.newDrawable("sliderBackS");
sliderStyle.disabledBackground.setMinWidth(0);
sliderStyle.disabledBackground.setMinHeight(0);
// and so on for other new drawables.
I'm not sure what your long term plans are, but typically you want all your skin's images to be part of a single Texture object so the SpriteBatch doesn't have to flush itself many times to draw your whole scene.
If for some reason you're not doing that, you can at least make all these solid color drawables use the same texture. It can simply be a one-pixel white texture that is shared by everything. Also, make sure you are disposing of the pixmap you use to create a texture, or you are leaking memory!
Pixmap pix = new Pixmap(1, 1, Pixmap.Format.RGBA8888);
pix.setColor(Color.WHITE);
pix.fill();
Texture tex = new Texture(pix);
pix.dispose();
skin.add(tex, "white");
Drawable blackDrawable = skin.newDrawable("white", Color.BLACK);
Drawable redDrawable = skin.newDrawable("white", Color.RED);
Slider.SliderStyle sliderStyle = new Slider.SliderStyle();
sliderStyle.disabledBackground = blackDrawable;
sliderStyle.disabledKnob = redDrawable;
sliderStyle.background = blackDrawable;
sliderStyle.knob = redDrawable;
Since you passed your Texture object to the Skin, the Skin will dispose of it when the Skin is disposed. Don't forget to dispose of the Skin in the dipose() method.
im currently developing a little duengon crawler and i wanna try to implement a healthbar using Scene2D. But theres a problem ... when i try to set the size of the progressbar its ever and ever the same size, doesnt matter if i do :
healthBar.setWidth(1f);
healthBar.setHeight(0.25f);
or
healthBar.setWidth(100);
healthBar.setHeight(25);
What im doing wrong ?? Heres how i created the stage ^^
camera = new OrthographicCamera(0,0);
camera.setToOrtho(false,Gdx.graphics.getWidth()/Box2dVars.UNIT,Gdx.graphics.getHeight()/Box2dVars.UNIT);
camera.zoom = (float) 0.75;
port = new ExtendViewport(camera.viewportWidth, camera.viewportHeight, camera);
stage = new Stage(port);
I also act and draw the stage every tick in the render method. Heres how i create the ProgressBar :
skin = new Skin(Gdx.files.internal("Scene2D-Skins/uiskin.json"));
healthBar = new ProgressBar(0, 100, 0.5f, false, skin, "default");
healthBar.setWidth(1f);
healthBar.setHeight(0.25f);
healthBar.setPosition(this.getPosition().x, this.getPosition().y);
this.gameScreen.stage.addActor(healthBar);
Did you see a mistake ?? What did i forgot ? :/ I would be happy about some help !
I'm using LibGDX and Scene2d and I want to create a pop-up that looks like the one shown in the image below.
So far, I created a table and set the background to a semitransparent color. Then I created an image with a white background. This image expands x, so it is centered. Now I want to have a label centered inside the image. To overlay these two actors, I created a group, but I couldn't find out how to center something in a group. How can I do this?
Here is my code:
Table table = new Table();
table.top();
table.setFillParent(true);
table.setBackground(getColoredBackground(color));
labelStyle = new Label.LabelStyle(font, fontColor);
label = new Label(message, labelStyle);
Image image = new Image(whiteBackground);
image.setSize(table.getWidth() - padding, label.getHeight() + extraHeight);
Group group = new Group();
group.setSize(image.getWidth(), image.getHeight());
group.addActor(image);
group.addActor(label);
table.add(group).expandX().padTop(padTop);
The group has it own coordinates system. It means that when you are setting actor position to (0,0) for example and then adding it to group which is actually at (100, 100) position then the object will be at (100, 100) position relative to the stage.
All you need to do is just to set:
label.setPosition( group.getWidth() / 2f - label.getWidth() / 2f, group.getHeight() / 2f - label.getHeight() / 2f );
after setting Group size. Remember that setting actor's position we are defining its left bottom corner position and that's why you need to also subtract the half of label width/height.
Of course you can modify the y position it doesn't have to be centered vertically also