javacameralibgdxtiledtmxtiledmap

how to maintain the appearance of the tiled map when I change the resolution in libGDX


i have created a test tiled map for a 2D game that i am programming. And everything is fine with!, but when i change the resolution the camera doesn´t fit the screen correctly.

I have a player sprite and the Tile map, and I use a resolution of 1366x768, as you can see the screen fit correctly:

enter image description here

but when i change the resolution, for example 640x480. The player doesn´t fit according to the new resolution as you can see in this picture:

enter image description here

The player seems bigger, but i want to fit the entire screen according to the new resolution, including all the sprites.

I think there is a problem with the cam rendering, but i don´t know what can i do to solve it. The camera is following the player movement and everything is ok with that, but i want to fit the screen game with the resolutions selected.

I'll put some parts of my code for you can see:

Here is the main code:

public class codeTiled implements ApplicationListener {

... //Variables.....

public void create() {      
    manager = new AssetManager();
    manager.setLoader(TiledMap.class, new TmxMapLoader());
    manager.load("C:/Users/HOME/Desktop/tilemap/TiledMap/data/maps/test.tmx", TiledMap.class);
    manager.finishLoading();
    map = manager.get("C:/Users/HOME/Desktop/tilemap/TiledMap/data/maps/test.tmx", TiledMap.class);
    batch=new SpriteBatch();
    float w = Gdx.graphics.getWidth();
    float h = Gdx.graphics.getHeight();
    camera = new OrthographicCamera(50, 50 * (h / w));

    float unitScale = 1 / 8f;
    renderer = new OrthogonalTiledMapRenderer(map, unitScale);
    player=new playerEx(100, 100, camera);
}

public void render() {      
    handleInput();
    Gdx.gl.glClearColor(1, 1, 1, 1);
    Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
    camera.update();
    renderer.setView(camera);
    renderer.render();
    batch.begin();
    player.render(batch);
    batch.end();
}

private void handleInput() {

    if (Gdx.input.isKeyPressed(Input.Keys.ESCAPE)){
        System.exit(0);
    }
     camera.zoom = MathUtils.clamp(camera.zoom, 0.1f, 100/camera.viewportWidth);
    float effectiveViewportWidth = camera.viewportWidth * camera.zoom;
    float effectiveViewportHeight = camera.viewportHeight * camera.zoom;
    camera.position.x = MathUtils.clamp(camera.position.x, effectiveViewportWidth / 2f, 100 - effectiveViewportWidth / 2f);
    camera.position.y = MathUtils.clamp(camera.position.y, effectiveViewportHeight / 2f, 100 - effectiveViewportHeight / 2f);
}

And this is some part of my player class:

public class playerEx {

...//Variables....

public playerEx(int x, int y, OrthographicCamera camera){
    this.camera=camera;
    recP= new Rectangle();
    recP.height = 64;
    recP.width = 64;
    recP.x = x;
    recP.y = y;

    imagen=new Texture(Gdx.files.internal("C:/Users/HOME/Desktop/tilemap/TiledMap/data/sprites/player/minigunattack.png"));
    imagen2=new Texture(Gdx.files.internal("C:/Users/HOME/Desktop/tilemap/TiledMap/data/sprites/player/minigunstand.png")); 
    TextureRegion[][] tmp=TextureRegion.split(imagen,
            imagen.getWidth()/5,imagen.getHeight());
    imagen1=new Texture(Gdx.files.internal("C:/Users/HOME/Desktop/tilemap/TiledMap/data/sprites/player/feet.png"));
    TextureRegion[][] tmp1=TextureRegion.split(imagen1,
            imagen1.getWidth()/5,imagen1.getHeight());
    movPlayer=new TextureRegion[5];
    movFeet=new TextureRegion[5];

    for(int i=0;i<5;i++){
        movFeet[i]=tmp1[0][i];
    }for(int i=0;i<5;i++){
        movPlayer[i]=tmp[0][i];
    }animationAttack=new Animation(0.08f,movPlayer);
    animationFeet=new Animation(0.10f,movFeet);
    tiempo=0f;                                                                                                                
}

Again, the camera is programmed to follow the player and it works fine. But when i want to change it to another resolution the sprite player doesn´t fit with the tiled map :(.

Hope somebody can help me with this... Thank you!.


Solution

  • I recommend you to use a viewport and some Constants values for your world.

    Firstly we define a default screen width and height in pixel. Doesn't matter how big the end screen will be. In my example, I say the default screen size is: 512x256 pixel.

    Secondly, I must decide how many pixels are one Meter. So if I say 256 pixels is one meter, my viewport shows 2x1 meter of my world. That's very small. If I want that my viewport shows for example 16 meter I can calculate: 512 / 16 = Pixel_Per_Meter. In this case 32.

    Finally, we create a Constants class:

    public class Constants {
    
        public static final float PPM = 32; // PPM = Pixel per Meter
        public static final float MPP = 1 / PPM; // MPP = Meter per Pixel
    
        public static final int WORLD_PIXEL_WIDTH = 512;
        public static final int WORLD_PIXEL_HEIGHT = 256;
        public static final float WORLD_WIDTH = WORLD_PIXEL_WIDTH / PPM; //in meter
        public static final float WORLD_HEIGHT = WORLD_PIXEL_HEIGHT / PPM; //in meter
    }
    

    Now when you see later in your game, the shown world is too small or too big, you can change the WORLD_PIXEL_WIDTH and WORLD_PIXEL_HEIGHT to show more or less

    Now we create our OrthographicCamera, FitViewport and OrthogonalTiledMapRenderer

    Viewport is a very important part of the game. If you will know more about Viewports read the viewport part of calling render method from another class and Libgdx set ortho camera

    So first create our OrthographicCamera 'camera' and our FitViewport 'viewport'

    camera = new OrthographicCamera();
    viewport = new FitViewport(Constants.WORLD_WIDTH, Constants.WORLD_HEIGHT, camera);
    camera.position.set(viewport.getWorldWidth() / 2, viewport.getWorldHeight() / 2, 0); // Differ from your I eat ann Apple 
    

    Then our SpriteBatch 'batch' and TiledMap 'map'

    batch = new SpriteBatch();
    map = app.getAssets().loadSingleAsset("map/" + level + ".tmx", TiledMap.class);
    

    And finally, our OrthogonalTiledMapRenderer 'mapRenderer'

    mapRenderer = new OrthogonalTiledMapRenderer(map, Constants.MPP);
    

    To render our world:

    @Override
    public void render(float delta) {
    
        camera.update();
    
        mapRenderer.setView(camera);
        mapRenderer.render();
    
        batch.setProjectionMatrix(camera.combined);
        batch.begin();
        player.draw(batch);
        batch.end();
    }