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也放大了,所以看起来又大又模糊。
解决方案:
通过比较您正在使用的 BitmapFont,使用更大的视口世界宽度和高度。
使用小尺寸的 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
每当我尝试将我的视口设置为舞台时,我放入场景中的演员都是模糊的并且非常大。我想将我的游戏世界大小设置为 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也放大了,所以看起来又大又模糊。
解决方案:
通过比较您正在使用的 BitmapFont,使用更大的视口世界宽度和高度。
使用小尺寸的 BitmapFont,或者您可以缩小尺寸,这样就不会缩小太多而看起来很丑。
skin.get("font-name",BitmapFont.class).getData().setScale(.25f);
您正在使用 Table
,因此您可能需要检查您的 Actor 在 cell/Table 中的位置。您可以通过此标志启用调试 stage.setDebugAll(true);
编辑
您正在使用来自 wiki
的 ExtendViewportExtendViewport 通过在一个方向上扩展世界来保持世界纵横比 没有黑条。世界首先被缩放以适应视口,然后较短的维度被加长以填充视口。
假设您的设备宽度和高度为 400 和 640,那么当您将视口更新为 400 和 640 时会发生什么。首先您的背景 Sprite 缩放高度并将其高度设置为 640(因为视口 worldheight 等于到背景高度)完成,现在是背景 Sprite 宽度的时候了,因为你设置宽度是高度的一半,所以缩放并设置大小 640/2 = 320。完成
你的问题来了,我的设备宽度是400,但我的背景精灵尺寸只有320(其余40*2单位是白色)。
使用48*80(大部分设备都是这个比例)而不是50*100