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.
Related
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
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!
I am trying to set my libgdx game to use a certain resolution on all android devices regardless of the devices native resolution.
to be specific my device has a resolution of 720x1280 and I want to use a resolution of 480x800.
On devices where the aspect ratio is different I don't mind how this is resolved.
My current code is
Camera cam = new OrthographicCamera(480,800);
view = new StretchViewport(480, 800, cam);
stage = new Stage();
Gdx.gl.glViewport(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
but all this seems to do is give me a 480x800 area in the bottom left corner (in which everything renders correctly)! How do I get libgdx to stretch this area to the whole of the devices screen?
Don't set the glViewport yourself, but let the Viewport do that for you.
You need the following code snippet in your resize() method.
public void resize(int width, int height) {
view.update(width, height);
}
I'm starting with AndEngine following this tutorial:
http://www.matim-dev.com/full-game-tutorial---part-1.html
But this guy looks like it's using a low resolution device for this test, I'm using a Galaxy S4 with a 1920x1080 resolution, yeah, damn high.
I know the thing about the RatioResolutionPolicy, but even though I'm using 800x480 in my S4 I got 2 white stripes from both sides (LANDSCAPE) like if it wasn't good resized, do I need to include another wallpaper for very high screen resolution devices?
Also, some coordinates that this guy used on the tutorial are bad placed on my S4, How am I supposed to make all devices compatible with this?
ADDING CODE:
private static int CAMERA_WIDTH = 800;
private static int CAMERA_HEIGHT = 480;
#Override
public EngineOptions onCreateEngineOptions() {
camera = new Camera(0, 0, CAMERA_WIDTH, CAMERA_HEIGHT);
EngineOptions engineOptions = new EngineOptions(true, ScreenOrientation.LANDSCAPE_FIXED, new RatioResolutionPolicy(CAMERA_WIDTH, CAMERA_HEIGHT), this.camera);
engineOptions.getAudioOptions().setNeedsMusic(true).setNeedsSound(true);
engineOptions.setWakeLockOptions(WakeLockOptions.SCREEN_ON);
return engineOptions;
}
Your problem is not the resolution, but the ratio. your camera has a ratio of 1.66, while your device has a ratio of 1.77, that is almost the same, but not the same.
You Need to calculate the ratio. Andengine will project the camera in any device, that's the magic of opengl and the camera, but if the ratio is not the same, it has to put that lines to avoid the image to be cropped or distorted, like when you see a 4:3 movie in a 16:9 tv
The solution would be to have a camera that has the same ratio has the device, so if the ratio is different, you dont have white stripes, but for example some extra background.
For example, in your case, you get the device size, get the ratio (1920/1080=1.7777) so you create a camera with that ratio. ie:
float device_ratio = DEVICE_HEIGHT/DEVICE_WIDTH;// in this case 1.7777
CAMERA_WIDTH = 800;
CAMERA_HEIGHT = 800/device_ratio ; /// this will be 450
So, you will have a camera of 800x450, and you can have backgrounds of that size (or some bigger that you can crop). This is, you don't have to use images of the full size of the device, but just create a camera of the same size of the device, and create backgrounds that look ok in that camera. You create your world in that 800x450 "canvas", and andengine will project it in the real device. Since the ratio is the same, everything will look ok. nothing cropped, nothing distorted, and no extra lines.
Now you has to think in a more relative way, since your camera will not be always be exactly the same, depending on the device. This is straightforward if you don't have many hardcoded values.
So I need to resize my sprites with respect to the phones screen size,
I do the following:
final Display display = getWindowManager().getDefaultDisplay();
cameraWidth = display.getWidth();
cameraHeight = display.getHeight();
//check to load male or female
Intent sender=getIntent();
String extraData=sender.getExtras().getString("char");
if(extraData.contains("1"))
{
isMale = 1;
}
else
{
isMale = 0;
}
mCamera = new Camera(0, 0, cameraWidth, cameraHeight);
return new Engine(new EngineOptions(true, ScreenOrientation.LANDSCAPE,
new RatioResolutionPolicy(cameraWidth, cameraHeight), mCamera)
.setNeedsMusic(true).setNeedsSound(true));
However, for sprites, ie the player and enemies, I give them an arbitrary size such as 50 pix by 50pix - Now on small screens they appear really large! how can I resize them with respect to the screen size?
Also, These images are loaded from assets folder, so they have nothing to do with HDPI and LHPI image folders.
Thanks in advance community.
You should either use SVG graphics that are scalable on different device screens.
What i would suggest is you set the CAMERA_WIDTH and HEIGHT to a screen size no matter what size device it is on.
For example, for a project i am making i have a camera width and height of 800x480.
This way you dont have to worry about resizing any sprites. They all appear the same on each device while scaling up by the engine with the RationResolutionPolicy.
This is the best way to go about this.
If you set the screens size based on the device you will have to supple different graphics for each.
So i would recommend using SVG graphics so that when the images are scaled up automatically by the engine they dont loose quality. OR you can use png's and make them large, that way they will only be scaled down. And as you know they wont lose image quality by scaling down.