如何处理 libGDX 中的不同纵横比? [英] How to deal with different aspect ratios in libGDX?

查看:26
本文介绍了如何处理 libGDX 中的不同纵横比?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经使用 libGDX 实现了一些屏幕,这些屏幕显然会使用 libGDX 框架提供的 Screen 类.但是,这些屏幕的实现仅适用于预定义的屏幕尺寸.例如,如果 sprite 用于 640 x 480 尺寸的屏幕(4:3 宽高比),则它不会在其他屏幕尺寸上按预期工作,因为 sprite 符合屏幕边界并且未缩放到屏幕尺寸一点也不.此外,如果 libGDX 提供了简单的缩放,那么我面临的问题仍然存在,因为这会导致游戏屏幕的纵横比发生变化.

I have implemented some screens using libGDX that would obviously use the Screen class provided by the libGDX framework. However, the implementation for these screens works only with pre-defined screen sizes. For example, if the sprite was meant for a 640 x 480 size screen (4:3 Aspect ratio), it won't work as intended on other screen sizes because the sprites go par the screen boundaries and are not scaled to the screen size at all. Moreover, if simple scaling would have been provided by the libGDX, the issue I am facing would have still been there because that would cause the aspect ratio of the game screen to change.

在网上搜索后,我发现了一个博客/论坛 讨论过同样的问题.我已经实现了它,到目前为止它运行良好.但我想确认这是否是实现这一目标的最佳选择,或者是否有更好的选择.下面是显示我如何处理这个合法问题的代码.

After researching on internet, I came across a blog/forum that had discussed the same issue. I have implemented it and so far it is working fine. But I want to confirm whether this is the best option to achieve this or whether there are better alternatives. Below is the code to show how I am dealing with this legitimate problem.

论坛链接: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);
        }
    }
}

更新:我最近了解到 libGDX 有一些自己的功能来保持我想在这里讨论的纵横比.在互联网上搜索纵横比问题时,我遇到了几个论坛/开发者,他们遇到了如何在不同屏幕尺寸上保持纵横比?"的问题.上面发布了一个真正对我有用的解决方案.

UPDATE: I recently came to know that libGDX has some of its own functionality to maintain aspect ratios which I would like to discuss here. While searching the aspect ratio issue across the internet, I came across several forums/developers who had this problem of "How to maintain the aspect ratio on different screen sizes?" One of the solutions that really worked for me was posted above.

后来当我继续为屏幕实现 touchDown() 方法时,我发现由于 resize 的缩放,我实现 touchDown() 的坐标 会发生很大的变化.在使用一些代码根据屏幕调整大小转换坐标后,我在很大程度上减少了这个数量,但我没有成功地保持它们的精确度.例如,如果我在纹理上实现了 touchDown(),调整屏幕大小会使纹理区域上的 touchListener 向右或向左移动一些像素,具体取决于调整大小,这显然是不希望的.

Later on when I proceeded with implementing the touchDown() methods for the screen, I found that due to scaling on resize, the co-ordinates on which I had implemented touchDown() would change by a great amount. After working with some code to translate the co-ordinates in accordance with the screen resize, I reduced this amount to a great extent but I wasn't successful to maintain them with pin point accuracy. For example, if I had implemented touchDown() on a texture, resizing the screen would shift the touchListener on the texture region some pixels to the right or left, depending on the resize and this was obviously undesired.

后来我才知道舞台类有自己的原生功能来保持纵横比(boolean stretch = false).现在我已经使用舞台类实现了我的屏幕,它很好地保持了纵横比.但是在调整大小或不同的屏幕尺寸时,生成的黑色区域总是出现在屏幕的右侧;那就是屏幕没有居中,如果黑色区域很大,这会很丑.

Later on I came to know that the stage class has its own native functionality to maintain the aspect ratio (boolean stretch = false). Now that I have implemented my screen by using the stage class, the aspect ratio is maintained well by it. However on resize or different screen sizes, the black area that is generated always appears on the right side of the screen; that is the screen is not centered which makes it quite ugly if the black area is substantially large.

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

Can any community member help me out to resolve this problem?

推荐答案

现在怎么做:

由于这是 libgdx 上最著名的问题之一,我将对其进行一点更新:

LibGDX v1.0 引入了Viewport 来处理这个问题.它更易于使用,并且扩展策略是可插拔的,这意味着一行可以改变行为,您可以使用它来查看哪一个最适合您的游戏.

LibGDX v1.0 introduced Viewport to handle this problem. It is a lot easier to use and the scaling strategy is pluggable, which means a single line can change the behaviour and you can play with it and see which one fits your game the best.

您需要了解的所有信息都可以在这里找到.

Everything you need to know about it can be found here.

这篇关于如何处理 libGDX 中的不同纵横比?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆