LibGdx Understanding the viewports and associtate

2019-09-14 18:02发布

问题:

Whenever I try to set my viewport to a Stage, the actors, that I puting into the Scene are blured and very large. I want to set my Game world size as a rectangle of 50x100 units and then scale everything (Sprites, actors, labels, fonts) according that units. Every state inharitate form a class State which provides render function etc.

public abstract class State {
    public static final float GAME_SIZE_WIDTH = 50 ;
    public static final float GAME_SIZE_HEIGHT = 100 ;
    protected OrthographicCamera camera;

    protected  GameStateManager gsm;
    protected Viewport viewport;

    public State(GameStateManager gsm) {
        this.gsm = gsm;
        camera = new OrthographicCamera();
        viewport = new ExtendViewport(GAME_SIZE_WIDTH, GAME_SIZE_HEIGHT, camera);
        viewport.apply();
        camera.position.set(GAME_SIZE_WIDTH / 2, GAME_SIZE_HEIGHT  / 2, 0);
    }

    public  abstract void handleInput();
    public abstract void update(float dt);
    public abstract void render (SpriteBatch sb);
    public abstract void dispose();
    public abstract void resize(int width, int height) ;
    }

In every State I want to add the Stage and pass the viewPort for my State class according to keep the GAME_SIZE_WIDTH /GAME_SIZE_HEIGHT dimension, but Ive got unadjusted backgrounds (even if its full HD picture the white border on the left) and the Buttons are blured with unadjusted text on it.

 public class MenuState extends State implements InputProcessor {

private Skin skin;
private Stage stage;

private Sprite background;
private Table table;
private  TextButton startButton,quitButton;
private Sprite flappyButton;
private Sprite chodzenieButton;
private Sprite memoryButton;
private Sprite rememberSquare;
private  static  final String TAG = "kamil";
private Vector3 touchPoint;

public MenuState(GameStateManager gsm) {
    super(gsm);

    skin = new Skin(Gdx.files.internal("button/uiskin.json"));
    stage = new Stage(viewport);
    table = new Table();
    table.setWidth(stage.getWidth());
    table.align(Align.center | Align.top);

    table.setPosition(0,GAME_SIZE_HEIGHT);
    startButton = new TextButton("New Game",skin);
    quitButton = new TextButton("Quit Game",skin);
   startButton.addListener(new ClickListener() {
        @Override
        public void clicked(InputEvent event, float x, float y) {
            Gdx.app.log("Clicked button","Yep, you did");
            event.stop();
        }
    });

    table.padTop(5);
    table.add(startButton).padBottom(5).size(20,10);
    table.row();
    table.add(quitButton).size(20,10);

    stage.addActor(table);

    background =new Sprite(new Texture(Gdx.files.internal("backgrounds/bg.jpg")));
    background.setSize(GAME_SIZE_WIDTH,GAME_SIZE_HEIGHT);
    background.setPosition(0,0);
    touchPoint= new Vector3();

    InputMultiplexer im = new InputMultiplexer(stage,this);
    Gdx.input.setInputProcessor(im);
   flappyButton=new Sprite(new Texture("menuButton/floopyBirdButtonTexture.png"));
    chodzenieButton =new Sprite(new Texture("menuButton/swipeMovementsButtonTexture.png"));
    memoryButton =new Sprite(new Texture("menuButton/memory.png"));
    rememberSquare = new Sprite(new Texture("menuButton/rememberSquare.png"));
    rememberSquare.setSize(20,10);
    flappyButton.setSize(20,10);
    chodzenieButton.setSize(20,10);
    memoryButton.setSize(20,10);
    flappyButton.setPosition(GAME_SIZE_WIDTH/2-flappyButton.getWidth()/2,GAME_SIZE_HEIGHT/2-flappyButton.getHeight()/2);
    chodzenieButton.setPosition(GAME_SIZE_WIDTH/2-flappyButton.getWidth()/2,flappyButton.getY()- chodzenieButton.getHeight() -2);
    memoryButton.setPosition(chodzenieButton.getX(),chodzenieButton.getY()- flappyButton.getHeight() -2);
    rememberSquare.setPosition(flappyButton.getX(),flappyButton.getY()+flappyButton.getHeight()+2);
}



@Override
public void render(SpriteBatch sb) {
    sb.setProjectionMatrix(camera.combined);
    sb.begin();
    background.draw(sb);
   flappyButton.draw(sb);
    chodzenieButton.draw(sb);
    memoryButton.draw(sb);
    rememberSquare.draw(sb);
    sb.end();
   stage.act(Gdx.graphics.getDeltaTime());
    stage.draw();
}

@Override
public void dispose() {
    flappyButton.getTexture().dispose();
    chodzenieButton.getTexture().dispose();
    background.getTexture().dispose();
}

@Override
public void resize(int width, int height) {
    Gdx.app.log("kamil","Resize");

    viewport.update(width,height);
}
@Override
public void handleInput() {
  if(Gdx.input.justTouched())
    {
       //

    viewport.unproject(touchPoint.set(Gdx.input.getX(),Gdx.input.getY(),0));
    if(flappyButton.getBoundingRectangle().contains(touchPoint.x,touchPoint.y)) {
        gsm.set(new FlopyBirdState(gsm));
    }
        else if (chodzenieButton.getBoundingRectangle().contains(touchPoint.x,touchPoint.y)){
        gsm.set(new ChodzenieState(gsm));
    }
    else if (memoryButton.getBoundingRectangle().contains(touchPoint.x,touchPoint.y)){
        gsm.set(new MemoryState(gsm));
    }
    else if (rememberSquare.getBoundingRectangle().contains(touchPoint.x,touchPoint.y)){
        gsm.set(new FoodEaterState(gsm));
    }}
}

回答1:

blured and very large : This is due to font size you're using.

Blured when some font scaled in appropriate manner, doesn't matter it is by you or by viewport.

You're using 50 and 100 as world width and height of viewport, and you're using BitmapFont from skin that having greater size as compare to 50 and 100. so when you update viewport by screenwidth and height then BitmapFont also scale up so look very large and blurry too.

Solution:

  1. Use some greater world width and height of viewport by comparing your BitmapFont that you're using.

  2. Use small size of your BitmapFont or you can scale down so that not scaled too much and look ugly.

    skin.get("font-name",BitmapFont.class).getData().setScale(.25f);
    

you're using Table so you may need to check where your Actor is in cell/Table. You can enable debugging by this flag stage.setDebugAll(true);

EDIT

You're using ExtendViewport, from wiki

The ExtendViewport keeps the world aspect ratio without black bars by extending the world in one direction. The world is first scaled to fit within the viewport, then the shorter dimension is lengthened to fill the viewport.

Let's suppose you're device width and height is 400 and 640, then what happen when you update viewport by 400 and 640. First your background Sprite scaled in height and set his height to 640(because viewport worldheight is equal to background height) done, now it's time for width of background Sprite because you set width is half of height so scaled and set size 640/2 = 320. done

Your problem arrive, my device width is 400 but my background sprite size is only 320 rest (40*2 unit is white from both side).

Use 48*80(most of devices is in this ratio) instead of 50*100