我一直在努力放置两个小视口,主视口占用整个屏幕空间,次要视口位于右上角(因为我们的想法是在那里绘制 FPS 计数器)
问题是我无法理解它到底是如何工作的,我一直在与人工智能交谈,经过一些更改后视口就可以工作了......但我需要理解为什么我的第一个实现不起作用,因为AI的答案很糟糕“有时你只需要使用手动视口放置,因为有时setScreenPosition可能无法按预期工作”
不工作的代码:
public class TestViewportGame extends Game {
private SpriteBatch batch;
private OrthographicCamera mainCamera;
private OrthographicCamera smallCamera;
private Viewport mainViewport;
private Viewport smallViewport;
private ShapeDrawerHack shapeDrawerHack;
@Override
public void create() {
batch = new SpriteBatch();
// Main camera setup
mainCamera = new OrthographicCamera();
mainViewport = new FitViewport(Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), mainCamera);
mainViewport.apply();
mainCamera.position.set(mainViewport.getWorldWidth() / 2, mainViewport.getWorldHeight() / 2, 0);
mainCamera.update();
// Small camera setup
smallCamera = new OrthographicCamera();
smallViewport = new FitViewport(200, 150, smallCamera);
smallViewport.setScreenPosition(Gdx.graphics.getWidth() - 200, Gdx.graphics.getHeight() - 150);
smallViewport.apply();
smallCamera.position.set(smallViewport.getWorldWidth() / 2, smallViewport.getWorldHeight() / 2, 0);
smallCamera.update();
// Initialize ShapeDrawer
shapeDrawerHack = new ShapeDrawerHack(new ShapeDrawer(batch));
shapeDrawerHack.load();
}
@Override
public void render() {
ScreenUtils.clear(Color.BLACK);
// Render main scene
mainViewport.apply();
mainCamera.update();
batch.setProjectionMatrix(mainCamera.combined);
batch.begin();
// Draw main scene elements here
batch.end();
// Render small viewport
smallViewport.apply();
smallCamera.update();
batch.setProjectionMatrix(smallCamera.combined);
batch.begin();
shapeDrawerHack.getShapeDrawer().filledRectangle(0, 0, smallViewport.getWorldWidth(), smallViewport.getWorldHeight(), Color.RED);
batch.end();
}
@Override
public void resize(int width, int height) {
mainViewport.update(width, height);
smallViewport.update(width, height);
}
@Override
public void dispose() {
batch.dispose();
shapeDrawerHack.dispose();
}
}
工作代码:
public class TestGame extends Game {
private SpriteBatch batch;
private OrthographicCamera mainCamera;
private OrthographicCamera smallCamera;
private Viewport mainViewport;
private Viewport smallViewport;
private ShapeDrawerHack shapeDrawerHack;
@Override
public void create() {
batch = new SpriteBatch();
// Main camera setup
mainCamera = new OrthographicCamera();
mainViewport = new FitViewport(Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), mainCamera);
mainViewport.apply();
mainCamera.position.set(mainViewport.getWorldWidth() / 2, mainViewport.getWorldHeight() / 2, 0);
mainCamera.update();
// Small camera setup
smallCamera = new OrthographicCamera();
smallViewport = new FitViewport(200, 150, smallCamera);
smallCamera.position.set(smallViewport.getWorldWidth() / 2, smallViewport.getWorldHeight() / 2, 0);
smallCamera.update();
// Initialize ShapeDrawer
shapeDrawerHack = new ShapeDrawerHack(new ShapeDrawer(batch));
shapeDrawerHack.load();
}
@Override
public void render() {
ScreenUtils.clear(Color.BLACK);
// Render main scene
mainViewport.apply();
mainCamera.update();
batch.setProjectionMatrix(mainCamera.combined);
batch.begin();
// Draw main scene elements here
batch.end();
// Render small viewport
Gdx.gl.glViewport(Gdx.graphics.getWidth() - 200, Gdx.graphics.getHeight() - 150, 200, 150);
smallCamera.update();
batch.setProjectionMatrix(smallCamera.combined);
batch.begin();
shapeDrawerHack.getShapeDrawer().filledRectangle(0, 0, smallViewport.getWorldWidth(), smallViewport.getWorldHeight(), Color.RED);
batch.end();
// Reset viewport to main camera
Gdx.gl.glViewport(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
}
@Override
public void resize(int width, int height) {
mainViewport.update(width, height);
smallViewport.update(width, height);
}
@Override
public void dispose() {
batch.dispose();
shapeDrawerHack.dispose();
}
}
注意事项:
提前致谢!
在 libGDX 中,处理多个视口确实看起来不可预测,特别是在管理具有自己的摄像机和视口的不同阶段或场景时。让我们详细分析一下视口的工作原理以及使用多个视口时可能导致不可预测行为的原因。
视口类型:libGDX 提供了多种类型的视口(
ScreenViewport
、FitViewport
、FillViewport
、StretchViewport
、ExtendViewport
、ScalingViewport
)。其中每一个都有不同的策略来处理调整大小和缩放,这可能会影响事物的显示方式。
视口和相机的关系:视口链接到相机。当您创建视口时,它会根据屏幕尺寸和所选的缩放策略来管理相机的视口尺寸。
处理多个视口:当您有多个视口时,每个视口都与不同的阶段或渲染通道相关联,需要仔细处理它们各自的相机更新。
视口更新不当:
viewport.update(width, height)
或 resize()
的 ApplicationListener
方法中调用 Screen
来完成。冲突的视口:
相机配置不正确:
操作顺序:
视口特定问题:
FillViewport
或 StretchViewport
)在不同的屏幕宽高比下可能表现不同,可能导致看似不可预测的剪切或拉伸。使用 FitViewport
可以帮助保持宽高比,但会增加黑条,而 StretchViewport
可能会扭曲宽高比以适合屏幕。持续更新:
update()
方法中的每个视口上调用 resize()
。渲染顺序和清屏:
Gdx.gl.glClear(...)
)。然后,按预期顺序渲染每个视口/阶段。每个视口单独批次:
Stage
对象或使用不同视口进行自定义渲染,请确保每个阶段都有自己的 SpriteBatch
或至少在渲染每个阶段之前正确设置投影矩阵。调试视口状态:
ShapeRenderer
等调试工具来绘制视口和相机的边界。这可以帮助识别错位或缩放问题。记录和逐步验证:
以下是如何设置两个视口并正确渲染它们的示例:
public class MyScreen implements Screen {
private Stage stage1;
private Stage stage2;
private FitViewport viewport1;
private ScreenViewport viewport2;
public MyScreen() {
viewport1 = new FitViewport(800, 600); // Fixed aspect ratio
viewport2 = new ScreenViewport(); // Stretches to screen
stage1 = new Stage(viewport1);
stage2 = new Stage(viewport2);
}
@Override
public void render(float delta) {
// Clear the screen
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
// Update and draw first stage
stage1.act(delta);
stage1.draw();
// Update and draw second stage
stage2.act(delta);
stage2.draw();
}
@Override
public void resize(int width, int height) {
viewport1.update(width, height, true); // Keep aspect ratio
viewport2.update(width, height, false); // Stretch to fill screen
}
// Other required methods...
}
如果遵循这些准则,您应该可以更好地控制 libGDX 中多个视口的行为。如果您提供有关您遇到的“不可预测”行为的更多细节,我可以提供更有针对性的建议。 apne 电视加拿大。