LibGDX Stage - How to Stretch ImageButton? - java

Recently we got a issue regarding stretching an ImageButton in LibGDX's Stage API.
We have a graphics-heavy game that can pick a textureatlas based on your screen (either HDPI, MDPI or LDPI etc)
We build our game with 480x854 as virtual resolution and scale nicely using viewports on devices that differ from that.
We explicitly set each sprite size to make sure it scales well regardless what size the source texture is.
However, sometimes it could happen that a texture is slightly larger or smaller than the actual size it is displayed (for instance, a resolution of 320x480 will pick ldpi but the image is slightly smaller than the sprite it's displayed on)
For some reason the ImageButton can't work very well with that.
Here is an example of what I tried (in an imagebutton subclass):
#Override
public void setSize(float w, float h) {
super.setSize(w, h);
if (this.getImage() != null) {
//this.getImageCell().expand().fill();
this.getImage().setSize(w, h);
this.getImage().setScaling(Scaling.stretch);
//this.getImage().invalidate();
this.invalidate();
}
}
What I'm trying to achieve is that when I call button.setSize(300, 320) it will actually stretch the image to become 300x320. But instead, it either shows the button using the original size of the source image (without workaround above) or shows it completely washed / stretched out (also out of proportions) using the workaround above.
I hope someone might have a good fix for this, I'm banging my head on this one for 2 days now :(
Thanks a lot! Have a nice weekend!
Update
I managed to display the image button correctly now but outside a panel I used to have it in. Inside the panel it goes showing up weird again. I'll keep this up-to-date and when I find it myself I'll post a valid answer.

Related

How can I stop my textures from becoming low resolution in libGDX

I am using libGDX to make a small game, I made a little sprite (32x32) that is shown in the center of the screen. For some reason when I render the texture to the screen it loses its quality. Since the textures are so small I made the screen width and height 200 and 100 respectively. Any tips or answers would be much appreciated.
Your sprite (32x32) needs to be displayed on an area which is larger than 32x32, meaning that the image needs to be upscaled and interpolated (i.e. pixels between the 32 known ones need to be calculated). A common approach is smooth (often times linear) interpolation to fill in the additional pixels, which works well for photorealistic textures; it appears to have occurred here.
For pixel-art, you likely want "nearest-neighbor" interpolation instead. While the exact way to set it depends on the structure of your code, you may be able to do something like:
textureObject.setFilter(TextureFilter.Nearest, TextureFilter.Nearest);

Is there a proper way to scale actors on the Stage?(Libgdx)

I'm making an android app which has Libgdx Stage handling the HUD. But how can I scale things I add to Stage?
I've tried some manipulations with Camera, Viewport, and none of the work properly. Let's say I want my ImageButton placed in the right top corner of the screen. I managed to do that manipulating with table positioning, it seems to be fine. But the problem appear when I run my app on my phone. The ImageButton positioned right but it's kinda small :-)
Thing is I want ImageButton look like on (540,800) resolution screen.
ImageButton is (65,65).
When it comes to bigger screensizes ImageButton starts to look small because it does not scale(or the viewport and camera stuff dont work well, I dont think the actual scaling is truly necessary)
I suggest you to check the documentation about Viewports, which is pretty clear, although a bit dated : https://github.com/libgdx/libgdx/wiki/Viewports
If you don't need to mess with the camera, don't bother to declare one. Simply use a stage, with includes automatically an orthographic camera. If you declare an Actor within the bounds of the viewport, it should scale properly depending on the type of viewport you selected. For instance :
FillViewport vp = new FillViewport(800, 1280); // fills the screen, adapting itself to actual screen ratio
Stage stage = new Stage(vp);

How to use DIP/DP in LibGDX

I have been trying for the past hours to find a solution to this problem, but I can't seem to find anything.
I am developing a game for Android using LibGDX. In the emulator, the game looks fine, but when I play it on my phone, everything is different and misplaced. The solution I found for this is using Density Individual Pixels instead of regular pixels, so everything is placed corectly, no matter what device I use. However, I can't seem to find a proper way to do that. The only relevant solution I have found was to use this:
public static float pixelToDP(float dp) {
return dp * Gdx.graphics.getDensity();
}
I tried resizing some of the objects using the formula above, but they are still different from the emulator.
Please, if anyone has a solution that doesn't involve changing the Ortographic Camera(already tried those), help me!
This answer is just to add to the what TomGrill said in the comments.
The reason your game looks fine in the emulator is because you have used values that fits the resolution of the emulator.
If you position a sprite at 100,100 on a 1920x1080 resolution, the sprite will be in the upper (or lower, depending on how you orient your y axis) left corner.
On a 200,200 resolution, the sprite will be placed in the middle of the screen.
The size of the sprite is also dependent on the resolution / pixel density. If you have 1 pixel per sq inch, a 32x32 pixel sprite will be 32 inches wide and high. But on a screen with a high pixel density, lets say 100px pr. sq. inch. the 32x32 sprite will look pretty small.
This is where viewports come in. You choose a resolution, lets say 900x540 and you just code for this resolution. The viewport will make sure your game scales up or down to fit any resolution and pixel density. If you place a sprite in the middle of you 900x540 screen, the viewport will make sure that it is placed in the middle of a 1920x1080 resolution.
Even if you wanted to do these calculations yourself, Gdx.graphics.getDensity(); is not of any use on its own. You need the width and the height of the physical screen to find the resolution. And what you would be doing next is reinventing the wheel.

LIBGDX drawables on devices with different densities/resolutions

I'm new to LIBGDX game development, and I have faced my first problem. I've created 9.patch drawables (buttons) using texture packer. This drawables can be used on low density and also extra high density screens and quality is the same.
If I run my project with that drawable on desktop project the image shown is okay and perfect size. If I run project on low density android device, drawable becomes huge (almost half of the screen). And also If I run project on extra high density android device the button becomes really small.
So my question is, how to handle drawables in LIBGDX, so the ratio (screen:image size), stays the same no matter resolution/density..?
If your button is a text button. Change the font of your text.
If you are using image button, this might help you
It kind of depends on what you're drawing...If you are just drawing an image, I've found it easier to specify a float width and height in the last 2 parameters of the draw method. If you are using a camera with a fixed viewport size, you can simply use a fixed percentage of your camera viewport so it will always be the same dimensions and draw like this:
batch.draw(drawable,x,y,screenwidth * 0.5f,screenheight*0.5f);
However, if you are using buttons or some other widget inside of a table, you should specify the cell size and it should automatically be resized based on the size of the table cell. Something like:
myTable.add(myWidget).width(300).height(200);
Post up exactly what it is that you need to draw if you get a chance and it will be easier to figure out what needs to happen.

Different look of application in android?

I'm developing a game with libgdx. I have a samsung infuse 4g and the game in my computer looks big but in my cellphone looks the way that i want to looks.
But when I run the application on the android machine simulator on eclipse it looks like on my computer: big
I'm using API_7 and I don't understand why. the size of my character is 128px,64px. I'm using Wide side and when I create the stage using libgdx I put this.
stage = new Stage(Gdx.graphics.getWidth(),Gdx.graphics.getHeight(),true);
If the Resoltion is higher your character get smaller because your stage always has the max resolution but your character still stays at its size. Resize the character and the stage on resize to a procentual for example and it should look the same. Else you need to provide some more informations so we can help
A small example would be. if you have a resolution of 1280x640 your char would be 10% of the screen right? Now imagin the resolution would be 640x320. Your character would be 20% of the screen. so you need to make it smaller to have the same proportion at the smaller screen. At a bigger one you need to make it bigger for the same proportion. Use the
#Override
public void resize(int width, int height) {
..... //resize here depending on the width and the height
}
in your screen to resize. I would recomend to use a OrthographicCamera which you give your stage stage.setCamera(cam);. So you just need to change the camera viewport in the resize and your stage does fit right. But keep track of the aspect_ratio.
You can even start working with a fixed resolution. So you have a resolution you work with and the rest is done by the zoom of your camera.
To have a fixed resolution you do zoom in and out with your camera to always have the whole resolution on the screen. It depend on the resolution your screen has. So if the resolution is smaller(of the screen where you display the game) you zoom out to show the whole gamefield. Else you zoom in till there is one edge at the viewport edges.(puh this seems to be hard stuff) Okay how does looks this?
#Override
public void resize(int width, int height) {
Gdx.app.log("Screen", "Resize screen: " + getName());
cam.viewportHeight = height;
cam.viewportWidth = width;
if (Config.VIRTUAL_VIEW_WIDTH / cam.viewportWidth < Config.VIRTUAL_VIEW_HEIGHT
/ cam.viewportHeight) {
cam.zoom = Config.VIRTUAL_VIEW_HEIGHT / cam.viewportHeight;
} else {
cam.zoom = Config.VIRTUAL_VIEW_WIDTH / cam.viewportWidth;
}
cam.update(); // update it ;)
}
This is actually everything. The VIRTUAL_VIEW_WIDTH and VIRTUAL_VIEW_HEIGHTare the resolution in px where i do work with at my game hud. Take care to use the right camera. So this is the camera that i gave my stage.
Maybe take a look at this blog. He does explain everything you need to know about Sceen2d and how to resize and so on.

Categories