如何在libGDX中处理不同的宽高比?

Raf*_*fay 80 android opengl-es aspect-ratio libgdx

我已经使用libGDX实现了一些屏幕,这显然会使用ScreenlibGDX框架提供的类.但是,这些屏幕的实现仅适用于预定义的屏幕尺寸.例如,如果精灵用于640 x 480大小的屏幕(4:3宽高比),它将无法按预期在其他屏幕尺寸上工作,因为精灵与屏幕边界相同并且不会缩放到屏幕尺寸一点都不 此外,如果libGDX提供了简单的缩放,我面临的问题仍然存在,因为这会导致游戏画面的宽高比发生变化.

在对互联网进行研究之后,我遇到了一个讨论同一问题的博客/论坛.我已经实现了它,到目前为止它工作正常.但我想确认这是否是实现这一目标的最佳选择,还是有更好的选择.下面是代码,以显示我如何处理这个合法的问题.

论坛链接:http://www.java-gaming.org/index.php? topic = 25685.new

public class SplashScreen implements Screen {

    // Aspect Ratio maintenance
    private static final int VIRTUAL_WIDTH = 640;
    private static final int VIRTUAL_HEIGHT = 480;
    private static final float ASPECT_RATIO = (float) VIRTUAL_WIDTH / (float) VIRTUAL_HEIGHT;

    private Camera camera;
    private Rectangle viewport;
    // ------end------

    MainGame TempMainGame;

    public Texture splashScreen;
    public TextureRegion splashScreenRegion;
    public SpriteBatch splashScreenSprite;

    public SplashScreen(MainGame maingame) {
        TempMainGame = maingame;
    }

    @Override
    public void dispose() {
        splashScreenSprite.dispose();
        splashScreen.dispose();
    }

    @Override
    public void render(float arg0) {
        //----Aspect Ratio maintenance

        // update camera
        camera.update();
        camera.apply(Gdx.gl10);

        // set viewport
        Gdx.gl.glViewport((int) viewport.x, (int) viewport.y,
        (int) viewport.width, (int) viewport.height);

        // clear previous frame
        Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);

        // DRAW EVERYTHING
        //--maintenance end--

        splashScreenSprite.begin();
        splashScreenSprite.disableBlending();
        splashScreenSprite.draw(splashScreenRegion, 0, 0);
        splashScreenSprite.end();
    }

    @Override
    public void resize(int width, int height) {
        //--Aspect Ratio Maintenance--
        // calculate new viewport
        float aspectRatio = (float)width/(float)height;
        float scale = 1f;
        Vector2 crop = new Vector2(0f, 0f);

        if(aspectRatio > ASPECT_RATIO) {
            scale = (float) height / (float) VIRTUAL_HEIGHT;
            crop.x = (width - VIRTUAL_WIDTH * scale) / 2f;
        } else if(aspectRatio < ASPECT_RATIO) {
            scale = (float) width / (float) VIRTUAL_WIDTH;
            crop.y = (height - VIRTUAL_HEIGHT * scale) / 2f;
        } else {
            scale = (float) width / (float) VIRTUAL_WIDTH;
        }

        float w = (float) VIRTUAL_WIDTH * scale;
        float h = (float) VIRTUAL_HEIGHT * scale;
        viewport = new Rectangle(crop.x, crop.y, w, h);
        //Maintenance ends here--
    }

    @Override
    public void show() {
        camera = new OrthographicCamera(VIRTUAL_WIDTH, VIRTUAL_HEIGHT); //Aspect Ratio Maintenance

        splashScreen = new Texture(Gdx.files.internal("images/splashScreen.png"));
        splashScreenRegion = new TextureRegion(splashScreen, 0, 0, 640, 480);
        splashScreenSprite = new SpriteBatch();

        if(Assets.load()) {
            this.dispose();
            TempMainGame.setScreen(TempMainGame.mainmenu);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

更新:我最近才知道libGDX有一些自己的功能来维护宽高比,我想在这里讨论.在互联网上搜索宽高比问题时,我遇到了一些论坛/开发人员,他们遇到了"如何在不同的屏幕尺寸上保持宽高比?"的问题.其中一个真正适用于我的解决方案已在上面发布.

后来当我继续实现touchDown()屏幕的方法时,我发现由于调整大小,我实现的坐标touchDown()会发生很大的变化.在使用一些代码来根据屏幕调整大小来转换坐标之后,我在很大程度上减少了这个数量但是我没有成功地用针点精度来维护它们.例如,如果我已touchDown()在纹理上实现,则调整屏幕大小会将纹理区域上的touchListener移动到右侧或左侧的某些像素,具体取决于调整大小,这显然是不受欢迎的.

后来我才知道舞台类有自己的本机功能来维持宽高比(boolean stretch = false).现在我已经使用舞台类实现了我的屏幕,因此它可以很好地保持宽高比.但是,在调整大小或不同屏幕尺寸时,生成的黑色区域始终显示在屏幕的右侧; 也就是说,如果黑色区域非常大,则屏幕不居中,这使得它非常难看.

任何社区成员都可以帮我解决这个问题吗?

noo*_*one 50

现在该怎么做:

由于这是关于libgdx最着名的问题之一,我将给它一些更新:

引入LibGDX v1.0 Viewport来处理这个问题.它使用起来容易得多,并且缩放策略是可插拔的,这意味着单行可以改变行为,你可以玩它并看看哪一个最适合你的游戏.

您可以在此处找到您需要了解的所有信息.


Raf*_*fay 24

编辑: libGDX已经发展.最佳答案现在是这个用户没有人.请务必查看Viewport文档的链接..

正如史蒂夫布莱克发布了舞台课上报道的问题的链接,我去那里发现这个问题(实际上不是我的问题)已经在最新的夜魇中解决了.

在网上搜索我遇到的问题之后,我找不到任何解决方案,所以决定直接联系报告错误的人.在那之后,他在libgdx论坛上回复了我,我很感激他帮助我.链接在这里

这是一行代码,您所要做的就是:

在resize()方法中:

stage.setViewport(640, 480, false);
stage.getCamera().position.set(640/2, 480/2, 0);
Run Code Online (Sandbox Code Playgroud)

其中640 X 480是TextureRegion的分辨率,用于描述预期的宽高比.如果您的TextureRegion大小为320 X 240,则应将两个参数更改为新分辨率以执行此操作.

实际解决我的问题的原始人的个人资料链接

  • 在libGDX 0.9.6中,stage.setViewport(640,480,false)就足够了,因为它已经包含对stage.getCamera().position.set(640/2,480/2,0)的调用; (6认同)

Ste*_*ell 7

左/右或上/下的黑条看起来比仅仅扭曲整个场景以适应屏幕更好.如果您将宽高比定位在可能范围的中间(4:3可能是低端,16:9可能是高端),那么对于大多数设备,条形应保持较小.即使在更大的屏幕上,你也可以使用大部分屏幕,而且你已经有了这个人的代码,所以这很容易.如果这只是libgdx内置的一个选项,那就更好了.

但是,我认为最好的方法是使用整个屏幕.我还没有这样做,但这将是我为下一个项目采取的方法.这个想法是,如果有人有更宽的屏幕,那么他们应该看到更多的侧面.克里斯普鲁特谈到如何在他的一次谈话中这样做(链接到谈话中的现场 - 实际上,整个事情实际上非常好).我们的想法是缩放高度,然后将视口设置得足够宽以适合屏幕.OpenGL应该负责显示其余部分.他这样做的方式就在这里.

对于libgdx,也许有一种简单的方法可以通过在舞台上移动相机来实现这一点,但是我从未真正使用过scene2d.在任何情况下,将应用程序作为本机可调整大小的窗口运行是一种更简单的方法来测试多个屏幕尺寸,而不是创建一堆AVD.


Nat*_*teS 5

请参阅官方文档中视口部分的最后一部分:https: //code.google.com/p/libgdx/wiki/scene2d#Viewport