Libgdx之Viewport 屏幕适配

教程总目录: http://blog.csdn.net/zqiang_55/article/details/50878524

在游戏开发的时候我们一般会设置一个世界的大小,这个大小是固定的,游戏的位置也是固定的。但是Android的各种分辨率,为了使游戏元素在不同的分辨率显示在相同比例的位置上,我们需要为游戏做适配。不过好在Libgdx给我定义了Viewport。

Viewport的种类

这里写图片描述

Viewport解释

  1. ScreenViewport:没有确定的世界尺寸,世界尺寸是由屏幕尺寸来确定的。

    /* Creates a new viewport using a new {@link OrthographicCamera}. /
    public ScreenViewport () {
    this(new OrthographicCamera());
    }
    public ScreenViewport (Camera camera) {
    setCamera(camera);
    }
    @Override
    public void update (int screenWidth, int screenHeight, boolean centerCamera) {
    setScreenBounds(0, 0, screenWidth, screenHeight);
    setWorldSize(screenWidth * unitsPerPixel, screenHeight * unitsPerPixel);
    apply(centerCamera);
    }
    从上面可以看出初始化ScreenViewport的时候并没有指定世界大小,当调用update时才会根据屏幕来计算。默认屏幕上一个像素对应一个世界尺寸单位,这个比例可以调用setUnitsPerPixel (float unitsPerPixel)修改。这种形式下不会缩放,各个游戏元素按其尺寸(size)绘画,不会有黑框,屏幕尺寸越大,暴露的视野范围越大。换句话说屏幕尺寸小,那么有些游戏元素就不会显示,一般是游戏上部元素不显示

  2. ExtendViewport: 先采取Scaling.fit再向右或者向上扩展屏幕尺寸。

update (int screenWidth, int screenHeight, boolean centerCamera)

但是如果采用了maxWorldWidth则可能会出现黑屏
3. FitViewport: 保持高宽比例不变,按比例缩放世界直到有一个方向(上下或者左右)到达屏幕尺寸,世界居于屏幕中央,上下或者左右会留有黑框
4. FillViewport: 保持高宽比例不变,按比例缩放直到不留黑框,可能世界尺寸会超出屏幕尺寸,即有些有些元素在屏幕之外
5. StretchViewport:不保持高宽比例,将世界尺寸缩放到屏幕尺寸,但是有时候游戏元素会变形

如果是做游戏开发一般使用StretchViewport视图,懒人办法

测试代码:

    private static final float MIN_SCENE_WIDTH = 800.0f;
    private static final float MIN_SCENE_HEIGHT = 600.0f;
    private static final float MAX_SCENE_WIDTH = 1280.0f;
    private static final float MAX_SCENE_HEIGHT = 800.0f;

    Texture bg, sprite;
    SpriteBatch batch;
    Camera camera;
    BitmapFont font;

    private ArrayMap<String, Viewport> viewports; // 使用ViewPort相机已经在屏幕中央了
    private int currentViewport;
    private InputListenEvent inputListenEvent;

    @Override
    public void create() {
        bg = new Texture(Gdx.files.internal("background.jpg"));
        sprite = new Texture(Gdx.files.internal("badlogic.jpg"));
        batch = new SpriteBatch();
        camera = new OrthographicCamera();
        font = new BitmapFont();
        font.getData().setScale(2.0f);
        font.getRegion().getTexture().setFilter(TextureFilter.Linear, TextureFilter.Linear);

        createViewports();
        selectNextViewport();

        inputListenEvent = new InputListenEvent(); // 初始化监听事件
        Gdx.input.setInputProcessor(inputListenEvent); // Libgdx开始监听inputListenEvent
    }

    @Override
    public void resize(int width, int height) {
        viewports.getValueAt(currentViewport).update(width, height, true); // centerCamera=true将camera设置在world的中央

        getTextLog("resize");
    }

    @Override
    public void render() {
        Gdx.gl.glClearColor(0.39f, 0.58f, 0.92f, 1.0f);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

        batch.setProjectionMatrix(camera.combined);
        batch.begin();
        batch.draw(bg, 0, 0, viewports.getValueAt(currentViewport)
                .getWorldWidth(), viewports.getValueAt(currentViewport)
                .getWorldHeight());
        batch.draw(sprite, 0, 0);
        font.draw(batch, viewports.getKeyAt(currentViewport), 10, 400);
        batch.end();
    }

    @Override
    public void dispose() {
        bg.dispose();
        sprite.dispose();
        batch.dispose();
        font.dispose();
    }

    private void createViewports() {
        viewports = new ArrayMap<String, Viewport>();
        viewports.put("StretchViewport", new StretchViewport(MIN_SCENE_WIDTH, MIN_SCENE_HEIGHT, camera));
//      上面初始化和下面效果一致
//      viewports.put("StretchViewport", new ScalingViewport(Scaling.stretch, MIN_SCENE_WIDTH, MIN_SCENE_HEIGHT, camera));
        viewports.put("FitViewport", new FitViewport(MIN_SCENE_WIDTH,MIN_SCENE_HEIGHT, camera));
//      上面初始化和下面效果一致
//      viewports.put("FitViewport", new ScalingViewport(Scaling.fit, MIN_SCENE_WIDTH,MIN_SCENE_HEIGHT, camera));
        viewports.put("FillViewport", new FillViewport(MIN_SCENE_WIDTH, MIN_SCENE_HEIGHT, camera));
//      上面初始化和下面效果一致
//      viewports.put("FillViewport", new ScalingViewport(Scaling.fill, MIN_SCENE_WIDTH, MIN_SCENE_HEIGHT, camera));
        viewports.put("ScreenViewport", new ScreenViewport(camera));
        viewports.put("ExtendViewport (no max)", new ExtendViewport(MIN_SCENE_WIDTH, MIN_SCENE_HEIGHT, camera));
        viewports.put("ExtendViewport (max)", new ExtendViewport(MIN_SCENE_WIDTH, MIN_SCENE_HEIGHT, MAX_SCENE_HEIGHT,
                MAX_SCENE_WIDTH, camera));

        currentViewport = -1;
    }

    private void selectNextViewport() {
        currentViewport = (currentViewport + 1) % viewports.size;
        viewports.getValueAt(currentViewport).apply(true);  // 将camera至于屏幕中央

        viewports.getValueAt(currentViewport).update(Gdx.graphics.getWidth(),
                Gdx.graphics.getHeight(), true);  // centerCamera=true将camera设置在world的中央

        getTextLog("selectNextViewport");
    }

    private void getTextLog(String flag) {
        Gdx.app.log(flag, "selcected " + viewports.getKeyAt(currentViewport));

        Gdx.app.log(flag, "screentWidth= " + viewports.getValueAt(currentViewport).getScreenWidth() +
                "  screentHeight= " + viewports.getValueAt(currentViewport).getScreenHeight());

        Gdx.app.log(flag, "wordWidth= " + viewports.getValueAt(currentViewport).getWorldWidth() +
                "  wordHeight= " + viewports.getValueAt(currentViewport).getWorldHeight());

        Gdx.app.log(flag, "camera.x=" + camera.position.x + " camera.y="
                + camera.position.y);

        Gdx.app.log(flag, "screen x="+ viewports.getValueAt(currentViewport).getScreenX() + " y="+ viewports.getValueAt(currentViewport).getScreenY());

    }

    class InputListenEvent extends InputAdapter {
        // 可以参考上一节将的内容
        // 点击屏幕自动切换Viewport
        @Override
        public boolean touchDown(int screenX, int screenY, int pointer, int button) {
            selectNextViewport();
            return false;
        }

    }

测试效果图:其实这张图并不能看出具体效果,只是让大家知道我用了怎样的图片来测试
这里写图片描述

  • 6
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值