What is Gdx.graphics.getWitdth() measured in? - android

I'm using getWidth and getHeight a lot for scaling textures in my Libgdx project. What units are these in (pixels?)
Also, if I want the texture to look consistent on different phones, should I use getWidth/Height to scale, or some number value like width = 100, height = 50?

Yes, getWidth and getHeight are both measured in pixels. Although you can use these for your dimensions, usually what you'll want to do to get a consistent look across phones is to use a camera of some sort (for 2d games, generally an OrthographicCamera).
What you'll probably want to do is give the camera some fixed width and height, and then do all of your drawing through the camera's transformations. Something like:
SpriteBatch batch = new SpriteBatch();
OrthographicCamera camera = new OrthographicCamera(800, 600);
//some code here
batch.setProjectionMatrix(camera.combined);
batch.begin();
//draw your textures here
batch.end();
This should keep the scale of your images consistent across phones. Keep in mind that if there is too much of a stretch/compress, your textures may look distorted.

#clearlyspam23 that's exactly what I'm looking for, thank you! Just a note, set it up like:
OrthographicCamera camera = new OrthographicCamera();
camera.setToOrtho(false, 800, 600);
The other way looks like it positioned the camera origin at 800, 600.
Thanks again!

Related

libgdx resize image on multiple screens ratio

I know how to set Image width and height using pixel coords. Is there a way to set relative coords? I want to deal with multiple screens.
For example i have 1920x1080 screen size. And i have relative coords width (-100,100) and height = 200*1080/1920=112.5, height(-56.25, 56.25)
Can i use this relative coords to set width and height? and how to do it?
Is there any best practices to handle different screens ratio, handle orientation change correctly?
thanks in advance.
here is how i'm using it in my app:
create()
public void create() {
stage = new Stage();
Gdx.input.setInputProcessor(stage);
camera = new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
camera.setToOrtho(true, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
camera.update();
Skin skinBackground = new Skin();
skinBackground.add("background", new Texture(Gdx.files.absolute(FilePathSlicer.preparePath(taskSheet.background.getPicUrl()))));
background=new Image(skinBackground,"background");
if(background!=null) {
background.setWidth(width);
background.setHeight(height);
stage.addActor(background);
}
}
render
public void render() {
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
Gdx.gl.glClearColor(255/255f, 255/255f, 255/255f, 1);
stage.getBatch().setProjectionMatrix(camera.combined);
stage.act(Gdx.graphics.getDeltaTime());
stage.draw();
}
that is what Viewports are for. Viewport is kind on flexible are connected with a stage (which is actually something like transparency that you are adding items [buttons, labels etc...] on).
It cares for scaling in a way you defined by creating a proper type of viewport.
Main steps are:
//create() method
stage = new Stage(); //creating a stage
viewport = new FillViewport( screenWidth, screenHeight ); //creating viewport choosing a proper Viewport class - for example Fill
stage.setViewport( viewport ); //applying actors (buttons, labels etc...) to a stage
//render() method
stage.act(); //acting a stage to calculate positions of actors etc
stage.draw(); //drawing it to render all
//resize(width, height) method
viewport.update(width, height); //updateing viewport that it scales in proper way
You have many types of vieports like just for example:
FillViewport - stretches graphics to fill the display
FitViewport - adding black stripes when screen is to wide
ExtendViewport - cutting what is out of the screen
etc.
Of course you can have many stages and others viewport for each of them.
To read more about stages, actors and viewports visit: https://github.com/libgdx/libgdx/wiki/Scene2d
You don't have to care about screen orientation - all you need to do is to define your app orientation in android Manifest

Screens, resolutions, cameras, viewports chaos

I have read a few articles about resolutions, screens, viewports and cameras on the mobile phone, but I am much more confused now, that I were before. Could you please help me to keep up with issue and handle it, as currently I am working on mobile game, but without any success. I am using LibGDX.
Regarding to answer below I changed my program (thanks for explanation Xoppa :)
New piece of code:
#Override
public void create () {
orthographicCamera = new OrthographicCamera();
fillViewport = new FillViewport(960, 600, orthographicCamera);
orthographicCamera.position.set(orthographicCamera.viewportWidth * 0.5f, orthographicCamera.viewportHeight * 0.5f, 0);
fillViewport.apply();
}
.
#Override
public void render () {
Gdx.gl.glClearColor(0.22f, 0.22f, 0.22f, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
...
}
.
#Override
public void resize (int width, int height) {
fillViewport.update(960, 600);
orthographicCamera.position.set(960 * 0.5f, 600 * 0.5f, 0);
}
But the result is the same.
Output:
Two small dots are my players. :(
Even if I change the Viewport resolution, size of my players do not change. The only thing that change was visible resolution of viewport, behind it I do not see mz players. I sketeched it for better imagination (values are just for imagination).
Physics body of my players:
public Character(Vector2 startPosition) {
BodyDef bodyDef = new BodyDef();
bodyDef.type = BodyType.DynamicBody;
bodyDef.position.set(startPosition);
// Create our body in the world using our body definition
body = Physic.gameWorld.createBody(bodyDef);
// Create a circle shape and set its radius to 6
CircleShape circle = new CircleShape();
circle.setPosition(new Vector2());
circle.setRadius(0.39f);
// Create a fixture definition to apply our shape to
FixtureDef fixtureDef = new FixtureDef();
fixtureDef.shape = circle;
fixtureDef.density = 1f;
// Create our fixture and attach it to the body
body.createFixture(fixtureDef);
circle.dispose();
}
Even if I change the radius of the circle, body will need much more energy to manipulate with and also body is not big enough. Of course I can not set the radius to value which is more than 10f as Box2D doc not recommended it.
But I do not see anything, when I run it, or created physical world objects are too small or flattened (physical world configuration and initialization is good I think; radius of circle physical objects are 0.39). Or am I missing something in the code, some statements or anything else?
But I think I have problem with correct understanding of mentioned issues.
Could you please help me with this or explain it?
First make sure to understand what a camera and viewport is and does. Perhaps this example might help:
Imagine that you're in the park and take a photo with your camera/smartphone of a tree and a bench. The bench is e.g. 3 meters wide and half a meter in height and depth. The tree might be e.g. half a meter wide and 10 meters in height. Now if you look at the photo on the screen of your camera/smartphone, then you'll see that the bench is no longer 3 meters wide, instead it is just a few millimeters wide. The actual size depends on how you've setup your camera (e.g. zoom) as well as the resolution of the photo (in pixels) and the density of the screen you're watching it on.
So practically in the example above the bench and the tree have two different sizes: the actual size in the park in the physical world and the size on the screen you're watching the photo on. Of course the tree and the bench don't actually shrink depending on the photo, they stay the same size. The size on the photo is only the size of the projection of the tree and the bench.
Projection is practically transforming world objects onto the screen, based on various camera settings (like zoom, position, etc.).
The park is much bigger than only the portion you've taken the photo of. When you took the photo you decided which portion of the park (the physical world) you want to project onto the photo. Let's call this the park's viewport.
Likewise you also don't have infinite storage to project the photo, you'll have to define the portion (the resolution of the photo) you want to project onto. Let's call this the photo's viewport.
The park's viewport is expressed in real world units, like meters or inches e.g. The photo's viewport is expressed in pixels (the resolution you've set it to).
When making a game you typically aren't making a photo but rendering to screen. Therefor the photo's viewport is then called the screen viewport. And when making a game your park might not even exist, your game world is virtual. Therefor the park's viewport is then called the virtual viewport.
On a small side-note: pixels are always integers, therefor screenviewport is always expressed in int. World units like meters or inches can be fractional, therefor virtualviewport is always expressed in float.
The Camera class of libgdx does exactly what is described above, it performs the the projection of your virtual world onto the screen. However, in practice that comes with some problems. E.g. not every screen has the same aspect ratio. Therefor you need to define how you want to cope with differences in aspect ratio. E.g. add black bars, expand the virtual world or stretch it, etc.
The Viewport class of libgdx solves that problem by implementation various strategies you can choose from on how to define your virtualviewport and screenviewport. To do this it encapsulates (and manages) a camera for you.
In your code you've given it a OrthographicCamera in the constructor to manage, which is typically used for 2D games. The virtualviewport you've set the OrthographicCamera to in the constructor is overwritten though. Because you've chosen to use a ScreenViewport. This is an implementation that makes the virtualviewport (the portion of the park) the same as the screenviewport (the portion of the screen).
It is very unlikely that you want to use that viewport implementation. Instead you probably want to use e.g. a FillViewport:
public void create () {
viewport = new FillViewport(50f, 50f);
}
This creates a virtualviewport that grows if needed to maintain aspect ratio. The 50 by 50 is in world units, e.g. meters or inches.
Now we need to tell the viewport which screenviewport to use. This depends on the size of the screen of the device and is therefor best set in the resize method.
public void resize (int width, int height) {
viewport.update(width, height);
}
All other code of these methods of you can be removed, you dont need them. You dont need to update the camera in your render method. You can just use the viewport as you normally would. And if you need access to the camera directly (but not to modify it, only to read e.g. its projection matrix), then you can use:
viewport.getCamera()

How to scale sprites in libgdx?

I made an app in libGDX. I have a sprite which is 256*256 pixels. But this is too big, so I want to scale it down to 160*160 pixels. How could I do that?
You can achieve it using a version of the draw method in the SpriteBatch class, which is
batch.draw(Sprite, float x, float y, float width, float height)
So you can scale to 160 * 160 pixels by calling:
batch.begin();
batch.draw(yourSprite, 0, 0, 160, 160);
batch.end();
You should note that scaling is an expensive operation especially for low -end devices and should be used when absolutely necessary. Ideally, you should resize all your images/textures before using them in your project.
Instead of manually drawing the sprite using batch.draw(sprite...) you can use sprite.draw(Batch batch). Using the sprite's own method will do all of the object's transformations for you, which makes things a bit easier to handle. This is of course assuming you are using the actual Sprite class to hold your texture, which I would highly recommend.

Libgdx, scale sizes based on device screen

I am working on my first libgdx app, a game. I have made some apps in IntelliJ before, but this is different. I am struggling with how my game will look over several devices, how to make everything scale appropriately.
If you can take a look at how I have it now, and maybe help me understand how it 'should' be to get the most out of it?
I have three classes, 'MyGame', 'MainMenuScreen' and 'GameScreen'.
// MyGame.java
WIDTH = Gdx.graphics.getWidth();
HEIGHT = Gdx.graphics.getHeight();
// MainMenuScreen
public void show(){
WIDTH = Gdx.graphics.getWidth();
HEIGHT = Gdx.graphics.getHeight();
camera = new OrthographicCamera();
camera.setToOrtho(false, 800, 480);
}
// GameScreen
public void show(){
camera = new OrthographicCamera();
camera.setToOrtho(false, 800, 480);
}
So, the 800, 480 is pixels, lets say I want to add something to this, and make it 32x32px (height, width), will it look the same on all devices? Bigger on large screens, and smaller on small screens, but always relevant to, lets say a background that is 800x480px?
I hope you understand what I am getting at. I posted the code I thought was relevant to the question, if u want more code, just say so, just tell me what you need.

Why is my sprite not being drawn correctly (libgdx)?

I have a 1024x1024 pixel image in a jpg file. I am trying to render it onscreen with libgdx such that it fills the whole screen. At this stage I am not concerned with the image preserving its aspect ratio.
In my show() method I parse the jpg and initialize the sprite thus:
mWidth = Gdx.graphics.getWidth();
mHeight = Gdx.graphics.getHeight();
mCamera = new OrthographicCamera(1, mHeight/mWidth);
mBatch = new SpriteBatch();
mTexture = new Texture(Gdx.files.internal("my jpg file"));
mTexture.setFilter(TextureFilter.Linear, TextureFilter.Linear);
TextureRegion region = new TextureRegion(mTexture);
mSprite = new Sprite(region);
mSprite.setSize(0.99f, 0.99f);
mSprite.setOrigin(mSprite.getWidth()/2, mSprite.getHeight()/2);
mSprite.setPosition(-mSprite.getWidth()/2, -mSprite.getHeight()/2);
and in the render() method, I draw the sprite thus
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
mBatch.setProjectionMatrix(mCamera.combined);
mBatch.begin();
mSprite.draw(mBatch);
mBatch.end();
but all that is actually rendered is a blank white screen. What am I doing wrong?
You should use
mCamera = new OrthographicCamera(mWidth, mHeight);
in stead of
mCamera = new OrthographicCamera(1, mHeight/mWidth);
in most cases, unless you want to scale things in a different way.
Check if your code has actually found and read the file successfully. If not, check things like full path, file extension, intermediate spaces etc.
In resize method, try adding following
mBatch.getProjectionMatrix().setToOrtho2D(0, 0, mWidth, mHeight);
If it isn't working even then, I'd recommend falling back to the working libgdx logo sprite being drawn when you create a new project with setup ui. Change things slowly from there.
For reference, use https://code.google.com/p/libgdx-users/wiki/Sprites
Good luck.
To the best of my knowledge, mSprite.setSize(0.99f, 0.99f); sets the pixel width and height of a sprite whereas setScale scales the sprite's dimensions. Setting setSize to something larger such as 256 x 256 should make your sprite visible and setting it to the resolution of the screen should make it fill the screen if all goes well. The examples linked by Tanmay Patil are great so look into them if you're having trouble.

Categories

Resources