Сцена, окно просмотра, камера, масштабирование и Nexus 7

Я новичок в Android, и я также учусь использовать libgdx. Я нашел несколько руководств, в которых используется метод кодирования «DisplayScreen extends AbstractScreen», и они используют Stage и Actor для отображения вывода. Моя интерпретация этого метода кодирования заключается в том, что DisplayScreen будет использовать все в AbstractScreen, если только это не @Override (пожалуйста, поправьте меня, если я ошибаюсь).

Поэтому, если я помещу код в AbstractScreen resize(), чтобы масштабировать дисплей до большего экрана, сохраняя при этом соотношение сторон; сцена в DisplayScreen должна изменить ее размер, чтобы она соответствовала большему экрану. Основная цель состоит в том, что я хочу сосредоточить разработку игр только в среде 800x480 и полностью игнорировать все разные размеры/разрешения. Resize() в AbstractScreen сделает всю тяжелую работу по масштабированию и адаптации моей игры к любому разрешению.

Пожалуйста, позвольте мне использовать мой тестовый пример для лучшего объяснения. У меня нет проблем с отображением моего черного фона 800x480 на моем телефоне. Однако тот же фон отображался, НО не сохранял соотношение сторон на Nexus 7.

Этот турориал устранил мою проблему, упомянутую выше (я принял две черные полосы по обеим сторонам экран). Однако у меня есть небольшая проблема с интеграцией этого решения в метод «DisplayScreen extends AbstractScreen».

См. этот снимок экрана здесь. Мои проблемы:

  1. Почему мой черный ящик не подгоняется под размер экрана, оставляя две красные полосы по обеим сторонам экрана?
  2. Я не понимаю, почему на моем Nexus 7 черное изображение отображается только в разрешении 766x480?

Будет здорово, если кто-нибудь укажет мне правильное направление.

Код для awesomegame

package com.example.somegame;

import com.badlogic.gdx.Game;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.assets.AssetManager;
import com.example.somegame.screens.DisplayScreen;

public class awesomegame extends Game {

public static AssetManager AssetManager = new AssetManager();

@Override
public void create() {
}

@Override
public void render() {
    super.render();
}

@Override
public void resize(int width, int height) {
    super.resize(width, height);
    setScreen( new DisplayScreen(this) );

}

@Override
public void setScreen(Screen screen) {
    super.setScreen( screen );
}

Код для абстрактного экрана

package com.example.somegame.screens;

import com.example.somegame.awesomegame;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.utils.Scaling;

public class AbstractScreen implements Screen{

private awesomegame awesomegame;
private Stage stage;

private BitmapFont font;
    private SpriteBatch batch;
private OrthographicCamera camera;

public AbstractScreen(awesomegame awesomegame) {
    this.awesomegame = awesomegame;

    camera = new OrthographicCamera();
    camera.setToOrtho(false, 800, 480);
    camera.update();

    stage = new Stage(800, 480, false);
}

@Override
public void render(float delta) {
    stage.act( delta );
    Gdx.gl.glClearColor( .5f, .5f, 0f, 1f );
    Gdx.gl.glClear( GL20.GL_COLOR_BUFFER_BIT );

    stage.draw();
}

@Override
public void resize(int width, int height) {
    Vector2 size = Scaling.fit.apply(800, 480, width, height);
    int viewportX = (int)(width - size.x) / 2;
    int viewportY = (int)(height - size.y) / 2;
    int viewportWidth = (int)size.x;
    int viewportHeight = (int)size.y;
    Gdx.gl.glViewport(viewportX, viewportY, viewportWidth, viewportHeight);
    stage.setViewport(800, 480, true);
}

Код для DisplayScreen

package com.example.somegame.screens;

import com.example.somegame.awesomegame;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.ui.Image;

public class DisplayScreen extends AbstractScreen {

private Image loadingBg;

private Stage stage;

float loadingPercent;

public DisplayScreen(awesomegame awesomegame) {
    super (awesomegame);
}

@Override
public void show()
{
    super.show();

    awesomegame.AssetManager.load("img/loading.atlas", TextureAtlas.class);
    awesomegame.AssetManager.finishLoading();

    stage = new Stage();

    TextureAtlas atlas = awesomegame.AssetManager.get("img/loading.atlas", TextureAtlas.class);


    loadingBg = new Image(atlas.findRegion("loadingBg"));

    loadingBg.setSize(800, 480);
    loadingBg.setX(0);
    loadingBg.setY(0);

    stage.addActor(loadingBg);

    // add all asset need to be loaded here. for example
    // awesomegame.AssetManager.load("img/whatever.pack", TextureAtlas.class);

}

@Override
public void render(float delta) {
    Gdx.gl.glClearColor( 1f, 0f, 0f, 1f );
    stage.draw();

}

person Ziiiii    schedule 24.10.2013    source источник


Ответы (2)


Nexus 7 имеет разрешение экрана 1280 x 800, но часть высоты используется для панели экранного меню (с кнопками назад/домой/меню).

Главный виновник вашего кода здесь, где вы пытаетесь применить определенное соотношение сторон, которое не соответствует этому скорректированному размеру, что приводит к появлению этих полос сбоку:

public void resize(int width, int height) {
    Vector2 size = Scaling.fit.apply(800, 480, width, height);
    ...
}

Похоже, вы вытащили эту функцию resize из другого поста stackoverflow. Я сделал то же самое, но переключился на что-то более простое, когда столкнулся с той же проблемой:

public void resize(int width, int height) {
    stage.setViewport(true, width,height);
    stage.getCamera().setToOrtho(false,width,height);
    ...
}
person strider    schedule 25.11.2013

Этот код работает для меня с последним обновлением:

OrthographicCamera - это камера, это не обрезает, просто изменяет область просмотра, поэтому ширина по-прежнему «во столько же» раз больше, чем фактическое окно/устройство.

public void resize(int width, int height) {
    int newW = width, newH = height;
    if (cam.viewportWidth > width) {
        float scale = (float) cam.viewportWidth / (float) width;
        newW *= scale;
        newH *= scale;
    }

    // true here to flip the Y-axis
    cam.setToOrtho(true, newW, newH);
}
person milosmns    schedule 11.08.2014