1
\$\begingroup\$

So I've done research about how to use Stage, Actor and Viewports etc. To optimize the game for most devices running Android. I'm pretty sure that the viewport is configured or the background image is just being drawn over the screen without actually using the viewport. That is fine though. So I'm basically telling the viewport to draw an image over the whole screen and it seems that that applies to actors also. So I guess the viewport is trying to draw the actor over the whole screen.

When testing the app on emulators with different screen sizes the actor is not resized (probably because of the viewport setting), but how can I get the actor to resize so that the actor fits in the world? The world will be the whole screen of the device.

Do I need to use two viewports where one is for UI (background so far) and another for the game? If I need to do that wouldn't the UI viewport need to be the screen size and the Game viewport holding the world size would have size constants? If so, then I don't have the whole screen size as the world, but drawing the Game viewport using the screen width and height would probably result in drawing the actor over the whole screen again, right?

And I've seen in some tutorials that they often set a constant unit of the world width and world height. Wouldn't that fail to fit all devices since they have a specific constant for width and height?

I want all of my Actors to be resized so that they fit inside the world (screen size).

UPDATE TO CLARIFY MY QUESTION

As you see the background is scaled up and down due to being drawn as the width and height of the screen, I guess, but I need the actors to also be scaled up or down. The actors can't remain the same size for all screens.

enter image description here

MyGdxGame

public class MyGdxGame extends ApplicationAdapter {

private OrthographicCamera camera;
private Stage stage;
private Viewport viewport;
private Texture textureBackground;

@Override
public void create () {
    camera = new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
    camera.position.set(Gdx.graphics.getWidth() / 2, Gdx.graphics.getHeight() / 2, 0);

    final float GAME_WORLD_WIDTH = Gdx.graphics.getWidth();
    final float GAME_WORLD_HEIGHT = Gdx.graphics.getHeight();
    viewport = new FitViewport(GAME_WORLD_WIDTH, GAME_WORLD_HEIGHT, camera);

    stage = new Stage(viewport);
    MyActor actor = new MyActor(new Texture("badlogic.jpg"));
    actor.setPosition(0, 0);
    stage.addActor(actor);
    stage.getViewport().apply();
    Gdx.input.setInputProcessor(stage);

    textureBackground = new Texture("TheWorld.png");
}

@Override
public void resize(int width, int height) {
    stage.getViewport().update(width, height);
    stage.getCamera().position.set(Gdx.graphics.getWidth() / 2, Gdx.graphics.getHeight() / 2, 0);
}

@Override
public void render () {
    Gdx.gl.glClearColor(1, 0, 0, 1);
    Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

    stage.getBatch().setProjectionMatrix(stage.getCamera().combined);
    stage.getCamera().update();

    stage.getBatch().begin();
    stage.getBatch().draw(textureBackground, 0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
    stage.getBatch().end();

    stage.act(Gdx.graphics.getDeltaTime());
    stage.draw();
}
}

MyActor

package com.mygdx.game;

import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.scenes.scene2d.Actor;

public class MyActor extends Actor {

    private Texture texture;
    public MyActor(Texture texture) {
        this.texture = texture;
    }

    @Override
    public void draw(Batch batch, float parentAlpha) {
        batch.draw(texture, getX(), getY());
    }
}

Images: The world LibGDX default image

Research links:

Using two viewports for UI and Game

Viewports and World units

LibGDX Viewport Tutorial

\$\endgroup\$
  • \$\begingroup\$ Read this: github.com/libgdx/libgdx/wiki/Orthographic-camera. This will maybe help you to understand where your problem lies. \$\endgroup\$ – Morchul Aug 2 '18 at 13:30
  • \$\begingroup\$ Seems to work well for Desktop applications but this is for Android. Can you point out where in my code my error is (Aspect ratios, viewport,camera)? And yeah, I got some more knowledge but I still can't tell. \$\endgroup\$ – kevvex Aug 2 '18 at 15:02
  • \$\begingroup\$ I can't test it on Android. I think your error lies in the MyActor.draw() method. Try to specify the size like: batch.draw(texture, 50, 50, 20, 20); \$\endgroup\$ – Morchul Aug 3 '18 at 9:09
  • \$\begingroup\$ Yeah, setting the actors width and height changes the size of the actor, but the size is never scaled down or up by the viewport because the size is always 20 x 20 now? \$\endgroup\$ – kevvex Aug 3 '18 at 10:25
3
\$\begingroup\$

I had take your code and change it a little bit.
I hope this will solve your problem otherwise I do not know what exactly your problem is.

I will recommend you to not use Gdx.graphics.getHeight/getWidth.
With the camera, you can use your own unit in this example 100 and the stage.getBatch().setProjectionMatrix(stage.getCamera().combined); will do the calculation for you. More about the camera and Matrix are on this site: github.com/libgdx/libgdx/wiki/Orthographic-camera

Code:

public class MyGdxGame extends ApplicationAdapter {
    private OrthographicCamera camera;
    private Stage stage;
    private Viewport viewport;
    private Texture textureBackground;

    private static final int WORLD_WIDTH = 100;
    private static final int WORLD_HEIGHT = 100;

    @Override
    public void create () {
        camera = new OrthographicCamera(WORLD_WIDTH,WORLD_HEIGHT);
        camera.position.set(camera.viewportWidth / 2, camera.viewportHeight / 2, 0);

        viewport = new StretchViewport(WORLD_WIDTH, WORLD_HEIGHT, camera);

        stage = new Stage(viewport);
        MyActor actor = new MyActor(new Texture("badlogic.jpg"));
        actor.setPosition(0, 0);
        stage.addActor(actor);
        stage.getViewport().apply();
        Gdx.input.setInputProcessor(stage);

        textureBackground = new Texture("TheWorld.png");
    }

    @Override
    public void resize(int width, int height) {
        stage.getViewport().update(width, height);
        stage.getCamera().viewportWidth = WORLD_WIDTH;
        stage.getCamera().viewportHeight = WORLD_HEIGHT * height / width;
        stage.getCamera().position.set(stage.getCamera().viewportWidth / 2, stage.getCamera().viewportHeight / 2, 0);
        stage.getCamera().update();
    }

    @Override
    public void render () {
        Gdx.gl.glClearColor(1, 0, 0, 1);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

        stage.getBatch().setProjectionMatrix(stage.getCamera().combined);
        stage.getCamera().update();

        stage.getBatch().begin();
        stage.getBatch().draw(textureBackground, 0, 0, 100,100);
        stage.getBatch().end();

        stage.act(Gdx.graphics.getDeltaTime());
        stage.draw();
    }
}


public class MyActor extends Actor {

    private Texture texture;
    public MyActor(Texture texture) {
        this.texture = texture;
    }

    @Override
    public void draw(Batch batch, float parentAlpha) {
//        batch.draw(texture, getX(), getY());
        batch.draw(texture, 50, 50, 20, 20);
    }
}
\$\endgroup\$
  • 1
    \$\begingroup\$ Thank you so much. This is exactly what I was trying to achieve. \$\endgroup\$ – kevvex Aug 3 '18 at 11:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.