LibGdx 了解视口并将其与 Scene2D 相关联

LibGdx Understanding the viewports and associtate it with a Scene2D

每当我尝试将我的视口设置为舞台时,我放入场景中的演员都是模糊的并且非常大。我想将我的游戏世界大小设置为 50x100 单位的矩形,然后根据该单位缩放所有内容(精灵、演员、标签、字体)。每个状态都包含一个 class 提供渲染功能等的状态

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) ;
    }

在每个 State 中,我想添加 Stage 并根据保留 GAME_SIZE_WIDTH /GAME_SIZE_HEIGHT 维度为我的州 class 传递 viewPort,但是我有未经调整的背景(即使它的全高清图片左侧有白色边框)并且按钮上有未经调整的文本而变得模糊。

 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));
    }}
}

模糊且非常大:这是由于您使用的字体大小所致。

当某些字体以适当的方式缩放时会变得模糊,无论是由您还是由视口缩放。

您使用 50 和 100 作为视口的世界宽度和高度,并且您使用的皮肤中的 BitmapFont 与 50 和 100 相比具有更大的尺寸。因此,当您按屏幕宽度和高度更新视口时,BitmapFont也放大了,所以看起来又大又模糊。

解决方案:

  1. 通过比较您正在使用的 BitmapFont,使用更大的视口世界宽度和高度。

  2. 使用小尺寸的 BitmapFont,或者您可以缩小尺寸,这样就不会缩小太多而看起来很丑。

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

您正在使用 Table,因此您可能需要检查您的 Actor 在 cell/Table 中的位置。您可以通过此标志启用调试 stage.setDebugAll(true);

编辑

您正在使用来自 wiki

的 ExtendViewport

ExtendViewport 通过在一个方向上扩展世界来保持世界纵横比 没有黑条。世界首先被缩放以适应视口,然后较短的维度被加长以填充视口。

假设您的设备宽度和高度为 400 和 640,那么当您将视口更新为 400 和 640 时会发生什么。首先您的背景 Sprite 缩放高度并将其高度设置为 640(因为视口 worldheight 等于到背景高度)完成,现在是背景 Sprite 宽度的时候了,因为你设置宽度是高度的一半,所以缩放并设置大小 640/2 = 320。完成

你的问题来了,我的设备宽度是400,但我的背景精灵尺寸只有320(其余40*2单位是白色)。

使用48*80(大部分设备都是这个比例)而不是50*100