Libgdx Scene2dUi 和视口

Libgdx Scene2dUi and Viewport

我已经在场景2d中做了我的布局并实现了它。但是尺码是个问题。它在我的 android phone 和桌面上有不同的对齐方式。

虽然我认为解决方案是使用视口,但我不知道如何正确实现它。

我实现它的方式让我出现白屏

 @Override
  public void show() {
    width=GameScreen.getGameWidth();
    height=GameScreen.getGameHeight();
    camera = new OrthographicCamera();
    camera.setToOrtho(true,width ,height);

    stage = new Stage(new FillViewport(width, height,camera)); 

    parameter.size = 40;
    parameter.color=Color.WHITE;
    parameter.flip=false;
    font12 = generator.generateFont(parameter); // font size 12 pixels
    generator.dispose();

    TextureAtlas atlas= new TextureAtlas(Gdx.files.internal("data/uiAtlas.atlas"));
    skin = new Skin(Gdx.files.internal("data/uiskin.json"));
    skin2= new Skin(Gdx.files.internal("data/achievementSkin.json"),atlas);
    Gdx.input.setInputProcessor(stage);

    mainTable = new Table();
    levelTable = new Table();

    stage.addActor(mainTable);
    mainTable.setFillParent(true);

    scrollPane = new ScrollPane(levelTable, skin);
    scrollPane.setFlickScroll(true);
    scrollPane.setFadeScrollBars(true);

    labelStyle=new LabelStyle();
    labelStyle.font=font12;

    makeLevelMenu();
}



public void makeLevelMenu() {
    for (int i = 0; i < 10; i++) {
        columnTable.add(new Table());

        // Image
        button.add(new ImageButton(skin2, "playButton"));
        columnTable.get(i).add(button.get(i)).colspan(2).padBottom(100)
                .padLeft(100).padRight(100).padTop(100);

        columnTable.get(i).row();
        // Enemy Label
        enemyLabel.add(new Label("Enemy " + (i + 1), labelStyle));
        columnTable.get(i).add(enemyLabel.get(i)).left().padBottom(300)
                .padTop(100);

        columnTable.get(i).row();
        // Battle Style
        battleStyle.add(new Label("Battle Style " + (i + 1), labelStyle));
        columnTable.get(i).add(battleStyle.get(i)).left().padBottom(100);

        levelTable.add(columnTable.get(i)).expand();
    }
    levelTable.debug();
    // achievementsTable.setFillParent(true);
    for (int i = 0; i < button.size(); i++) {
        final int k = i;
        button.get(k).addListener(new InputListener() {
            public boolean touchDown(InputEvent event, float x, float y,
                    int pointer, int button) {
                System.out.println("Level " + (k + 1) + "touchDown");
                return true;
            }

            public void touchUp(InputEvent event, float x, float y,
                    int pointer, int button) {

            }
        });
    }
    scrollPane.setScrollingDisabled(false, false);
    mainTable.add(scrollPane).expand().fill();
}



@Override
public void render(float delta) {
    Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
    Gdx.gl20.glClearColor(1, 1, 1, 1);
    stage.act(delta);
    stage.draw();
}

@Override
public void resize(int width, int height) {
    stage.getViewport().update(width, height, true);
}

LibGDX 确实提供 Vieworts 来帮助您解决不同的问题。我个人主要使用 FitViewport,它保持纵横比,其余的 "black" 框。还有许多其他视口,例如 StretchViewport,它完全符合您的期望。

如果一切设置正确,您可以轻松测试适合您游戏的内容。 The following code is straight from www.gamesfromscratch.com。他们描述了不太明显的视口的行为。

public class ViewportDemo extends ApplicationAdapter {
   SpriteBatch batch;
   Sprite aspectRatios;
   OrthographicCamera camera;
   Viewport viewport;

   @Override
   public void create () {
      batch = new SpriteBatch();
      aspectRatios = new Sprite(new Texture(Gdx.files.internal("Aspect.jpg")));
      aspectRatios.setPosition(0,0);
      aspectRatios.setSize(100,100);

      camera = new OrthographicCamera();
      viewport = new FillViewport(100,100,camera);
      viewport.apply();

      camera.position.set(camera.viewportWidth/2,camera.viewportHeight/2,0);
   }

   @Override
   public void render () {

      camera.update();
      Gdx.gl.glClearColor(1, 0, 0, 1);
      Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

      batch.setProjectionMatrix(camera.combined);
      batch.begin();
      aspectRatios.draw(batch);
      batch.end();
   }

   @Override
   public void dispose(){
      aspectRatios.getTexture().dispose();
   }

   @Override
   public void resize(int width, int height){
      viewport.update(width,height);
      camera.position.set(camera.viewportWidth/2,camera.viewportHeight/2,0);
   }

你可以自己做。创建任何图像,将其粘贴到舞台上并使用不同的视口和屏幕尺寸进行播放。也忘记使用像素,因为像素是硬件。

编辑

来自 www.gamesfromscratch.com 的上述实现并未显示如何在阶段中使用该实现。然而,这很简单。

stage = new Stage(viewport, batch);

现在舞台将使用您提供的视口和批次。现在只需在舞台上添加东西并像平常一样绘制它。

以下是我的代码,它使用舞台和 fitviewport 创建了一个非常基本的菜单屏幕。您确实需要自己的地图集和皮肤才能完成这项工作,check my answer here on SO to learn more about that.

public class MenuScreen implements Screen{

    private SpriteBatch batch;
    protected Stage stage;
    private Viewport viewport;
    private OrthographicCamera camera;
    private TextureAtlas atlas;
    protected Skin skin;

    public MenuScreen()
    {
        atlas = new TextureAtlas("atlas.txt");
        skin = new Skin(Gdx.files.internal("skin.json"), atlas);

        batch = new SpriteBatch();
        camera = new OrthographicCamera();
        viewport = new FitViewport(RealmOfConflict.WorldWidth, RealmOfConflict.WorldHeight, camera);
        viewport.apply();

        camera.position.set(camera.viewportWidth / 2, camera.viewportHeight / 2, 0);
        camera.update();

        stage = new Stage(viewport, batch);

        //Stage should controll input:
        Gdx.input.setInputProcessor(stage);
    }    

    @Override
    public void show() {
        //Create Table
        Table mainTable = new Table();
        //Set table to fill stage
        mainTable.setFillParent(true);
        //Set alignment of contents in the table.
        mainTable.top();

        //Create buttons
        TextButton playButton = new TextButton("Play", skin);
        TextButton optionsButton = new TextButton("Options", skin);
        TextButton exitButton = new TextButton("Exit", skin);

        //Add listeners to buttons
        playButton.addListener(new ClickListener(){
            @Override
            public void clicked(InputEvent event, float x, float y) {
                ((Game)Gdx.app.getApplicationListener()).setScreen(new PlayScreen());
            }
        });
        exitButton.addListener(new ClickListener(){
            @Override
            public void clicked(InputEvent event, float x, float y) {
                Gdx.app.exit();
            }
        });

        //Add buttons to table
        mainTable.add(playButton);
        mainTable.row();
        mainTable.add(optionsButton);
        mainTable.row();
        mainTable.add(exitButton);

        //Add table to stage
        stage.addActor(mainTable);
    }

    @Override
    public void render(float delta) {
        Gdx.gl.glClearColor(.1f, .12f, .16f, 1);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

        stage.act();
        stage.draw();
    }

    @Override
    public void resize(int width, int height) {
        viewport.update(width, height);
        camera.position.set(camera.viewportWidth / 2, camera.viewportHeight / 2, 0);
        camera.update();
    }

    @Override
    public void pause() {

    }

    @Override
    public void resume() {

    }

    @Override
    public void hide() {

    }

    @Override
    public void dispose() {
        skin.dispose();
        atlas.dispose();
    }
}

问题出在视口的相机中。您正在创建自己的相机并且不设置它的位置也不更新它。

如果没有理由创建自己的相机,只需依靠默认的舞台相机即可。而不是:

    camera = new OrthographicCamera();
    camera.setToOrtho(true,width ,height);

    stage = new Stage(new FillViewport(width, height,camera));

使用

    //no camera defining
    stage = new Stage(new FillViewport(width, height));

然后您的应用正常运行