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));
然后您的应用正常运行
我已经在场景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));
然后您的应用正常运行