I'm trying to make controls for my game, simply four buttons in total, 2 bottom right, 1 bottom left, 1 top right, but the skins are very stretched and act weird. I've tried different skins from the libgdx skin repository and they all act different, some are stretched a lot to the right, some are way to big. Here is my code:
table = new Table();
boostButtonSkin = new Skin(Gdx.files.internal("star-soldier/skin/star-soldier-ui.json"));
boostButton = new ImageButton(boostButtonSkin);
table.setWidth(stage.getCamera().viewportWidth);
table.setHeight(stage.getCamera().viewportHeight);
table.setDebug(true);
table.bottom().left();
table.add(boostButton).width(2).height(2);
stage.addActor(table);
Viewport width and height are 40, 24 respectively.
This sounds like you forgot to resize. Your resize method should look like below.
#Override
public void resize(int width, int height) {
stage.getViewport().update(width, height);
}
UI widgets in LibGDX are really designed for a ScreenViewport, since UI type stuff is usually ugly if not drawn pixel perfect. But you can get away with using other types of Viewport by setting trilinear filtering on your texture(s), turning off rounding for widgets that support it, and turning off "use integer positions" for any fonts.
But even then, you need to use virtual viewport dimensions that are fairly big (a few hundred units in each dimension). Your units are way too small for a NinePatch to be drawn correctly.
Aside from that, it looks like you are setting the table size based on the camera, but there isn't a guarantee that the camera is sized correctly by the time you are setting up your widgets. Instead of setting its size, call table.setFillParent(true) so it will automatically adapt to whatever the size of the viewport is.
Related
I need to be able to display a scene... :
Containing N cubes (with precise width, height and depth : each in the shape of "-/+[0|1|2].[0|1|...|9]+" - with seven digits after the comma : need a displaying with high-precision), with a given color (the same on all the faces of the cube)
I must be able to overlay a cube colored with white with another cube colored with red, of the same width, height and depth (of course, with same coordinates X, Y and Z) and the latter must hide the first without any problem of Z-fighting
I have coordinates X, Y and Z to place each cube in the scene
I must be able to rotate the entire scene (i.e. : each cube must rotate/move)
I must be able to zoom/unzoom in the scene, before or after having rotated the latter
I don't want to use OpenGL, or something else than the standard Java's API.
For the moment, I just display pixels in a 2D JFrame's panel (with the class Graphics and the overrided paint()). But my project makes me in need of switching with a 3D approach. I would want to just change my use of Graphics and paint(), and to keep my JFrame's panel.
Is it possible? What class do you advice me?
Consider JavaFX, as shown in Getting Started with JavaFX 3D Graphics. It uses the platform's available rendering pipeline internally, as discussed in JavaFX Architecture. Several related examples are shown here. If you stay with Swing, you can embed JavaFX content using JFXPanel, seen here. In particular, you can test overlap with this example.
Hell All & thanks for reading,
I recently started working on an 2D Android/Desktop project and have become stuck trying to display my sprites in the way i want.
I have a background Sprite that is 144(w) by 160(h) that I want to be able to position other sprites onto the screen relative to points on the background sprite.
I think I understand that if I create a camera/viewport that is 144 x 160 I would be able to position my sprites on the background sprite using the co-ordinates based on the 144 x 160 of the background sprite. This will work across the different screen resolutions found on mobile devices but will stretch the background sprite despite experimenting with the different viewport types (FillViewport, FitViewport etc..).
What I want to achieve is to have my background sprite to maintain it ratio across different screen resolutions and to be able to place other sprites over the background sprite. The placing of sprite need to work across different resolutions.
Apologies if my explanation is confusing or makes no sense. I would add some image to help explain but I reputation to add any to the post. However I think the TLTR question is "What is the correct way to display sprites on multiple screen resolutions while keeping a correct ratios and scaling to the screen size and position of sprite in a way that works across multiple resolutions?"
Thank, All Questions Welcome
A FitViewport would do what you described (maintain aspect ratio), but you will have black bars on some devices. Based on the code you posted on the libgdx forum, I see that you forgot to update the viewport in the resize method, so it is not behaving as designed.
However, for a static camera game like what you described, I think the best solution would be to plan your game around a certain area that is always visible on any device, for example, the box from (0,0) to (144,160). Then use an ExtendViewport with width and height of 144 and 160. After you update the viewport in resize, you can move the camera to be centered on the rectangle like this:
private static final float GAME_WIDTH = 144;
private static final float GAME_HEIGHT = 160;
public void create(){
//...
viewport = new ExtendViewport(GAME_WIDTH, GAME_HEIGHT);
//...
}
public void resize(int width, int height){
viewport.update(width, height, false); //centering by putting true here would put (0,0) at bottom left of screen, but then the game rectangle would be off center
//manually center the center of your game box
Camera camera = viewport.getCamera();
camera.position.x = GAME_WIDTH /2;
camera.position.y = GAME_HEIGHT/2;
camera.update();
}
Now your 144x160 box is centered on the screen as it would be with FitViewport, but you are not locked into having black bars, because you can draw extra background outside the 144x160 area using whatever method you like.
In your case 144:160 is a wider portrait aspect ratio than any screen out there, so you wouldn't need to worry about ever filling in area to the sides of your game rectangle. The narrowest aspect ratio of any phone or tablet seems to be 9:16, so you can do the math to see how much extra background above and below the game rectangle should be drawn to avoid black showing through on any device.
In this case it works out to 48 units above and below the rectangle that you would want to fill in:
144 pixels wide at 9:16 would be 256 tall.
(256 - 160) / 2 = 48
EDIT: I see from your post on the libgdx forum that you want the game area stuck at the top of the screen and the remainder of the area to be used for game controls. In that case, I would change the resize method like this, since you want to have the game area's top edge aligned with the top edge of the screen. You can also calculate where the bottom of the controls area will be on the Y axis. (The top will be at Y=0.)
public void resize(int width, int height){
viewport.update(width, height, false);
//align game box's top edge to top of screen
Camera camera = viewport.getCamera();
camera.position.x = GAME_WIDTH /2;
camera.position.y = GAME_HEIGHT - viewport.getWorldHeight()/2;
camera.update();
controlsBottomY = GAME_HEIGHT - viewport.getWorldHeight();
}
I'm not sure how you plan to do your controls, but they would need to fit in the box (0, controlsBottomY) to (GAME_WIDTH, 0). Keep in mind that there are some phones with aspect ratios as small as 3:4 (although rare now). So with your 0.9 aspect ratio, on a 3:4 phone only the bottom 17% of the screen would be available for controls. Which might be fine if it's just a couple of buttons, but would probably be problematic if you have a virtual joystick.
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.
Having a weird issue.
I have a Texture with four frames of a sprite Animation. Each frame is loaded as a TextureRegion.
Most of the time the Animation play without any issues, but occasionally it will draw too much of the Texture in one frame.
Here's an example of what I mean:
As you can see the UFO has a red bar on the left side of it. That red bar is part of a frame on the outside of the TextureRegion bounds stated in my code. (The red frame is just there to make it easier for me to measure, since there is transparency on all the corners)
Here's the Texture:
In the above sprite sheet the red frame for the slide at the top has the bounds 0, 0, 202, 71. The TextureRegion for the frame of the anim is 1, 1, 200, 69 -- at no point should any of the red frame be displayed, as far as I can tell.
I realise as a workaround I could just set the frame as transparent now that I have the measurements I need, but I'd like to keep the red frame in case I need to take the measurements again later, or replace the sprite images, etc, and really a workaround is just a band-aid whereas I'm hoping to find a proper solution to address the root of the issue -- the fact that it's drawing wrong seems to indicate a larger problem than what exists just in this particular case (eg, in a densely-packed Texture it might draw pixels from a different sprite frame or even a different sprite or a menu image or something like that).
Oh and one last note, in case it's helpful: when the SpriteBatch displays the image it applies a rotation based on the movement of the UFO (tilts to the left when moving left, etc). The glitchy red bars sometimes show up on the top, right, bottom, or left randomly (though most of the time they don't show up at all) however they only seem to show up when the UFO has a rotation of zero. (Again, I realise I could just include a check to see if rotation is 0 and then call the SpriteBatch.draw() method without the rotation figure, but that too would be treating the symptom rather than addressing the root of the problem).
Any thoughts from the learned masters?
Your frames of animation need padding around them to account for rounding error. Put two pixels of clear pixels all around each image. If you use TexturePacker to combine the images into your file, it will automatically add the two pixels of padding by default.
If you name your four images with an underscore-frame number suffix, like myAnimation_0.png, myAnimation_1.png, myAnimation_2.png, and myAnimation_3.png, then when you load your TextureAtlas, it allows you get the animation very easily.
Array<TextureRegion> myAnimationFrames = textureAtlas.findRegions("myAnimation");
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.