Как камера работает в Libgdx и вместе с Viewport - PullRequest
0 голосов
/ 15 января 2019

Если вы работаете с LibGdx, это займет немного времени, пока вы не зайдете в Camera и viewport. Если вы впервые работаете с камерой и Viewport, у вас возникнут вопросы о том, как она работает и как ее использовать. Итак:

  • Как я могу использовать камеру в LibGdx? Какова ширина и высота области просмотра?
  • Что такое видовой экран, как его использовать и как он работает вместе с камерой?

1 Ответ

0 голосов
/ 15 января 2019

Как я могу использовать камеру в LibGdx? Какова ширина и высота области просмотра?

Во-первых, важно, чтобы вы знали, что камера работает с единицами мира, а не с пикселями. Мировые юниты не являются обычными юнитами. Вы сами можете определить, сколько стоит одна Мировая Единица. Позже больше.

Сначала мы создаем OrthographicCamera a SpriteBatch и Texture:

private OrthographicCamera camera;
private SpriteBatch batch;
private Texture img;

@Override
public void create () {
    //We create a OrthographicCamera through which we see 50x50 World Units
    camera = new OrthographicCamera(50,50);
    batch = new SpriteBatch();
    img = new Texture("badlogic.jpg");
}

Мы создаем OrthographicCamera и в Конструкторе мы определяем, сколько Мировых Единиц мы видим, если смотрим через эту камеру в наш мир. В нашем примере 50 x 50 World Units это ширина и высота области просмотра. Итак, мы создали камеру с шириной области просмотра и высотой 50.

В методе render () мы визуализируем наше изображение:

@Override
public void render () {
    //Clear the screen (1)
    Gdx.gl.glClearColor(1, 1, 1, 1);
    Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

    //Set ProjectionMatrix of SpriteBatch (2)
    batch.setProjectionMatrix(camera.combined);

    batch.begin();
    //Draw image on position 0, 0 with width 25 and height 25 (3)
    batch.draw(img, 0, 0, 25, 25); 
    batch.end();
}

(1) Очистите экран, если мы этого не сделаем, каждая текстура будет рисовать поверх другой, и если мы нарисуем анимацию, мы увидим старые кадры.

(2) batch - это наш ящик, он рисует наши изображения, анимацию и т. Д. По умолчанию он рисует мир, в котором так много единиц мира, как на экране, и пикселей, поэтому в данном случае 1 единица мира = 1 пиксель. Но теперь мы увидим, что 50 x 50 Мировых Единиц не имеют значения, насколько велик экран. Чтобы сказать Партии, что он должен нарисовать то, что мы видим через нашу камеру, мы должны позвонить: batch.setProjectionMatrix(camera.combined);

(3) Теперь мы рисуем нашу img в Позиции 0,0, но 0, 0 не означает в Пиксельной позиции 0,0, это означает, что Изображение будет нарисовано в Мировой позиции 0,0, также ширина и высота не в пикселях, они в мировых единицах, поэтому img будет отображаться в позиции 0,0 25x25 больших мировых единиц. Таким образом, в окне просмотра 50x50 изображение занимает четверть всего экрана.

enter image description here

Изображение заполняет одну четверть всего экрана точно так, как ожидалось. Но почему он находится справа вверху, а не внизу слева?

Проблема в том, что центр камеры указывает на позицию 0,0 enter image description here

Итак, наше изображение нарисовано в позиции 0,0, он заполняет верхний правый угол. Мы должны установить положение камеры так, чтобы 0,0 находилось в нижнем левом углу:

camera = new OrthographicCamera(50,50);
camera.position.set(camera.viewportWidth / 2, camera.viewportHeight / 2, 0);

В методе render () мы должны добавить camera.update(), потому что каждый раз, когда мы меняем положение или масштаб, или что еще из камеры, мы должны обновлять камеру.

Теперь изображение внизу слева.

Где пиксели?

Мы всегда говорим о мировых единицах, но где же пиксели? Пиксели все еще там. Если у нас размер экрана 200 x 200 пикселей, партия всегда будет рисовать 200 x 200 пикселей. С помощью метода batch.setProjectionMatrix(camera.combined); мы только говорим пакету, сколько Мировых Единиц составляет один Пиксель.

Если у нас есть Экран с разрешением 200 x 200 пикселей, и мы создаем Камеру с областью просмотра 50 × 50 мировых единиц, SpriteBatch знает 1 WorldUnit = 4 пикселей. Теперь мы рисуем изображение размером 25 x 25 Мировых единиц, SpriteBatch знает, что он должен нарисовать изображение размером 25 * 4 = 100 пикселей.

Таким образом, пиксели все еще есть, но в мировых единицах легче думать. Если это не достаточно ясно, вот немного более подробное описание: Мировые Единицы Libgdx

Box2d

Также очень важно думать в мировых единицах, если вы используете Box2d, потому что Box2d работает с метрами. Таким образом, если вы создаете тело с Force off 5 на оси x, оно будет 5 м / с.

И теперь очень здорово работать с Мировыми Единицами, потому что вы можете сказать 1 Мировая Единица = 1 Метр, чтобы вы могли создать объект шириной 10, и вы знаете, что через одну секунду Тело будет в центре Объекта. , Если вы работаете с пикселями, у вас будет проблема, если у вас другой размер экрана.

Что такое видовой экран, как его использовать и как он работает вместе с камерой?

Теперь у нас большая проблема с экранами разных размеров. Внезапно у нас появился экран размером 350 x 200 пикселей, теперь изображение растянется и будет выглядеть не так хорошо, как раньше.

Для этой проблемы мы используем Viewports. Несколько Viewports: StretchViewport, FitViewport и ExtendViewport. Все окна просмотра вы можете найти здесь: https://github.com/libgdx/libgdx/wiki/Viewports.

Во-первых, что такое Viewport.

Представьте, что камера - это говорящий, говорящий по-английски. Различные размеры экрана - это другие люди, которые говорят по-немецки, по-французски, по-китайски и т. Д., А Viewport - переводчик. Переводчик не меняет смысла того, что говорит спикер английского языка, но он адаптирует его так, чтобы другие могли его понять. Это же камера и видовой экран. Viewport не говорит и не меняет то, что вы видите на экране, если вы запускаете программу. Он обрабатывает только то, что вы всегда видите одинаково на разных размерах экрана. Камера может жить без Viewport. Область просмотра не без камеры.

Добавить область просмотра Объект:

private Viewport viewport;

и метод resize ():

@Override
public void resize (int width, int height) {
    viewport.update(width, height);
}

StretchViewport

Создать StretchViewport:

camera = new OrthographicCamera(50, 50);
camera.position.set(camera.viewportWidth / 2, camera.viewportHeight / 2, 0);
viewport = new StretchViewport(camera.viewportWidth, camera.viewportHeight, camera);

В конструкторе StretchViewport мы определяем ширину и высоту области просмотра и камеры.

Теперь мы получаем тот же результат, что и раньше, если у нас разные размеры экрана. Изображения будут растянуты.

FitViewport

Может быть, мы не будем растягивать наши изображения, мы будем иметь значение относительно отношения x и y.

Соотношение x и y означает: это ширина Объекта 2 и высота 1, он всегда будет в два раза больше высоты, например, 200x100, 30x15, но не 20x15.

Создать FitViewport:

camera = new OrthographicCamera(50, 50);
camera.position.set(camera.viewportWidth / 2, camera.viewportHeight / 2, 0);
viewport = new FitViewport(camera.viewportWidth, camera.viewportHeight, camera);

Теперь изображение всегда будет квадратным. Чтобы увидеть столбики сбоку, нарисуем изображение размером с наш видовой экран:

batch.draw(img, 0, 0, 50, 50);

enter image description here enter image description here

Коэффициент изображения равен 1, поскольку 50 (ширина) / 50 (высота) = 1, поэтому изображение всегда будет иметь одинаковую ширину и высоту. Полоски на боковой панели находятся за пределами нашего видового экрана и будут нарисованы в цвете, который вы определили здесь: Gdx.gl.glClearColor(1, 1, 1, 1);

ExtendViewport

Может быть, мы не будем Bars на стороне, тогда мы можем взять ExtendViewport. ExtendViewport поддерживает пропорции мира без баров, расширяя мир в одном направлении. На экране, где соотношение сторон между шириной и высотой больше, вы увидите больше мира.

На экране с соотношением сторон 400x200 = (400/200 = 2) вы увидите больше, чем на экране 300x200 (300/200 = 1,5);

Чтобы показать это, создайте ExtendViewport и нарисуйте изображение больше, чем окно просмотра, и второе маленькое изображение:

camera = new OrthographicCamera(50, 50);
camera.position.set(camera.viewportWidth / 2, camera.viewportHeight / 2, 0);
viewport = new ExtendViewport(camera.viewportWidth, camera.viewportHeight, camera);

// in render() method
batch.begin();
batch.draw(img, 0, 0, 100, 50);
batch.draw(img, -20, 0, 20, 20);
batch.end();

Если мы сейчас запустим нашу Программу с размером экрана 200x200, мы увидим:

enter image description here

А если мы изменим размер экрана по оси x, чтобы сделать экран шире:

enter image description here

Теперь мы можем видеть больше на первом изображении и добавим второе изображение, но соотношение всегда будет одинаковым. Изображение растягивается только потому, что мы рисуем его 100х50, а не из-за изменения размера.

Я надеюсь, что это прояснит некоторые Вопросы о Камере и Окне просмотра, если вы узнаете больше, прочитаете и посмотрите некоторые учебники и прочитаете вики LibGdx: https://github.com/libgdx/libgdx/wiki

...