Эта страница представляет OrthographicCamera
класс и его использование. Ортографическая камера используется в 2D средах только там, где она реализует параллельную (ортографическую) проекцию и где нет масштабного фактора для конечного изображения, несмотря на местонахождения объекта в мире.
Описание
Класс Camera
работает как очень простая камера реального мира. В отношении камеры можно:
- Перемещать и вращать камеру вокруг
- Увеличивать и уменьшать масштаб
- Изменить область просмотра
- Делать проецирование/обратное проецирование в и из координат окна/пространства мира.
Использование камеры это простой способ перемещения вокруг игрового мира, без необходимости ручной работы с матрицами. Все операции с матрицей проекции и вида скрыты в реализации.
Следующее небольшое приложение демонстрирует использование простой OrthographicCamera
камеры для перемещения вокруг плоского мира. Чтобы представить мир (карту), его представляет плоская квадратная Mesh
с текстурой на поверхности. Картой является большой квадрат (1024x1024 пикселей) и окно просмотра 480x320 пикселей.
Окно просмотра это прямоугольная область видимая в любой момент из игрового мира. Если увеличить масштаб, то тем менее получиться прямоугольная область. Так как размер экрана не меняется, окно просмотра масштабируется до фактического разрешения.
public class OrthographicCameraController implements ApplicationListener { static final int WIDTH = 480; static final int HEIGHT = 320; private OrthographicCamera cam; private Texture texture; private Mesh mesh; private Rectangle glViewport; private float rotationSpeed; @Override public void create() { rotationSpeed = 0.5f; mesh = new Mesh(true, 4, 6, new VertexAttribute(VertexAttributes.Usage.Position, 3,"attr_Position"), new VertexAttribute(Usage.TextureCoordinates, 2, "attr_texCoords")); texture = new Texture(Gdx.files.internal("data/sc_map.png")); mesh.setVertices(new float[] { -1024f, -1024f, 0, 0, 1, 1024f, -1024f, 0, 1, 1, 1024f, 1024f, 0, 1, 0, -1024f, 1024f, 0, 0, 0 }); mesh.setIndices(new short[] { 0, 1, 2, 2, 3, 0 }); cam = new OrthographicCamera(WIDTH, HEIGHT); cam.position.set(WIDTH / 2, HEIGHT / 2, 0); glViewport = new Rectangle(0, 0, WIDTH, HEIGHT); } @Override public void render() { handleInput(); GL10 gl = Gdx.graphics.getGL10(); // Камера --------------------- / gl.glClear(GL10.GL_COLOR_BUFFER_BIT); gl.glViewport((int) glViewport.x, (int) glViewport.y, (int) glViewport.width, (int) glViewport.height); cam.update(); cam.apply(gl); // Текстурирование --------------------- / gl.glActiveTexture(GL10.GL_TEXTURE0); gl.glEnable(GL10.GL_TEXTURE_2D); texture.bind(); mesh.render(GL10.GL_TRIANGLES); } private void handleInput() { if(Gdx.input.isKeyPressed(Input.Keys.A)) { cam.zoom += 0.02; } if(Gdx.input.isKeyPressed(Input.Keys.Q)) { cam.zoom -= 0.02; } if(Gdx.input.isKeyPressed(Input.Keys.LEFT)) { if (cam.position.x > 0) cam.translate(-3, 0, 0); } if(Gdx.input.isKeyPressed(Input.Keys.RIGHT)) { if (cam.position.x < 1024) cam.translate(3, 0, 0); } if(Gdx.input.isKeyPressed(Input.Keys.DOWN)) { if (cam.position.y > 0) cam.translate(0, -3, 0); } if(Gdx.input.isKeyPressed(Input.Keys.UP)) { if (cam.position.y < 1024) cam.translate(0, 3, 0); } if(Gdx.input.isKeyPressed(Input.Keys.W)) { cam.rotate(-rotationSpeed, 0, 0, 1); } if(Gdx.input.isKeyPressed(Input.Keys.E)) { cam.rotate(rotationSpeed, 0, 0, 1); } } @Override public void resize(int width, int height) { } @Override public void resume() { } @Override public void dispose() { } @Override public void pause() { } }
Выше описанный класс это Libgdx приложение, которое будет использовать ортографическую камеру для перемещения вокруг мира. Опять же, миром является квадрат 1024x1024 пикселей. Для его представления, использована квадратная плоскость того же размера. Ортографическая камера позволяет легко работать с пикселями, даже если OpenGL это не нравится. Потому что нет Z оси, мы можно спокойно определить на мир, как 1024 единиц в ширину и длину. Если для текстуры используется изображение 1024x1024 и полигональная сетка тоже 1024x1024 единиц в ширину и длину, то мы используем идеальную проекцию пикселя.
static final int WIDTH = 480; static final int HEIGHT = 320;
Для окна просмотра будут использованы жестко заданные ширина и высота.
private OrthographicCamera cam; // 1 private Texture texture; // 2 private Mesh mesh; // 3 private Rectangle glViewport; // 4 private float rotationSpeed; // 5
- С помощью
OrthographicCamera
экземпляра, мы будет контролировать взгляд на мир. - Текстурное изображение мы будем показывать в роли карты (мира).
- Полигональная сетка, простой квадрат, к которому будет применена текстура.
- Прямоугольник представляющие окно просмотра
- Скорость в углах, с которой камера вращается при каждым вызовом визуализации.
@Override public void create() { rotationSpeed = 0.5f; // 1 mesh = new Mesh(true, 4, 6, new VertexAttribute(VertexAttributes.Usage.Position, 3, "attr_Position"), new VertexAttribute(Usage.TextureCoordinates, 2, "attr_texCoords")); // 2 texture = new Texture(Gdx.files.internal("img/sc_map.png")); // 3 mesh.setVertices(new float[] { -1024f, -1024f, 0, 0, 1, 1024f, -1024f, 0, 1, 1, 1024f, 1024f, 0, 1, 0, -1024f, 1024f, 0, 0, 0 }); // 4 mesh.setIndices(new short[] { 0, 1, 2, 2, 3, 0 }); // 5 cam = new OrthographicCamera(WIDTH, HEIGHT); // 6 cam.position.set(WIDTH / 2, HEIGHT / 2, 0); // 7 glViewport = new Rectangle(0, 0, WIDTH, HEIGHT); // 8 }
Все устанавливается в onCreate
методе.
- Устанавливает текущую скорость вращения в 0,5 градуса.
- Создает квадратную полигональную сетку. Первый параметр сообщает libgdx сделать сетку статической. Второй параметр сообщает, что сетка будет содержать 4 вершины (квадрат). Третий параметр представляет собой количество индексов, которые будут использоваться. Квадратных состоит из 2 треугольников и каждый треугольник имеет 3 вершины, таким образом, 2 * 3 = 6. Четвертый параметр сообщает о том, что позиция сетки описывается тремя значениями (x, y, z). Пятый параметр устанавливает значение равное 2 для атрибута позиции текстуры.
- Создает текстуру из
sc_map.png
файла. Загрузите текстуру и добавьте ее вassets/src
директорию. - Устанавливает массив вершин для полигональной сетки. Первые три элемента являются x, y, z координатами, а следующие два описывают текстурные координаты для этой вершины. Обратите внимание, что Z координата равна 0 , так как мы в 2D. Здесь 4 вершины.
- Установка индексов для вершин, что в результате был квадрат.
- Создание
OrthographicCamera
. Два параметра определяют ширину и высота окна просмотра, который будет создан. Мы будем использовать размер окна приложения. - Установка исходного положения камеры в центр экрана. Помните, что (0,0) находится в левом нижнем углу, поэтому начальное положение камеры будет нижней левой часть мира.
- Создание прямоугольника с левой нижней точкой (0,0), имеющего ширину и высоту заданную константами (эквивалентными размер окна).
Настройка выполнена. Камера была создана и расположена (указывает) в нижнем левом углу мира.
@Override public void render() { handleInput(); // 1 GL10 gl = Gdx.graphics.getGL10(); // 2 // Камера --------------------- / gl.glClear(GL10.GL_COLOR_BUFFER_BIT); // 3 gl.glViewport((int) glViewport.x, (int) glViewport.y, (int) glViewport.width, (int) glViewport.height); // 4 cam.update(); // 5 cam.apply(gl); // 6 // Текстурирование --------------------- / gl.glActiveTexture(GL10.GL_TEXTURE0); // 7 gl.glEnable(GL10.GL_TEXTURE_2D); // 8 texture.bind(); // 9 mesh.render(GL10.GL_TRIANGLES); // 10 }
- Управляет камерой через обновление ее позиции, масштаба, вращения, основанного на нажатие различных клавиш.
- Получает OpenGL экземпляре. Должна быть версия 1, так как версия 2 не поддерживается для
OrthographicCamera
. - Очищает экран (фактически буфер цвета).
- Устанавливает окно просмотра для OpenGL контекста, чтобы использовать окно просмотра, которое мы определили во время создания. В данный момент мы не обрабатываем изменение размеров.
- Обновляет камеры, очень важный шаг. Так как матрица проекции была изменена в
handleInput
методе, то этим просто сообщается камере о необходимости пересчитать матрицу проекции и отсечения для камеры. - Устанавливает текущею проекцию и матрицу вида модели камеры. Вызывается после обновления.
- Выбирается активная текстура.
- Включается возможность наложения текстур.
- Привязка текстуры к контексту.
- Визуализация полигональной сетки с картой.
private void handleInput() { if(Gdx.input.isKeyPressed(Input.Keys.A)) { cam.zoom += 0.02; } if(Gdx.input.isKeyPressed(Input.Keys.Q)) { cam.zoom -= 0.02; } if(Gdx.input.isKeyPressed(Input.Keys.LEFT)) { if (cam.position.x > 0) cam.translate(-3, 0, 0); } if(Gdx.input.isKeyPressed(Input.Keys.RIGHT)) { if (cam.position.x < 1024) cam.translate(3, 0, 0); } if(Gdx.input.isKeyPressed(Input.Keys.DOWN)) { if (cam.position.y > 0) cam.translate(0, -3, 0); } if(Gdx.input.isKeyPressed(Input.Keys.UP)) { if (cam.position.y < 1024) cam.translate(0, 3, 0); } if(Gdx.input.isKeyPressed(Input.Keys.W)) { cam.rotate(-rotationSpeed, 0, 0, 1); } if(Gdx.input.isKeyPressed(Input.Keys.E)) { cam.rotate(rotationSpeed, 0, 0, 1); } }
Метод handleInput()
просто опрашивает пользовательский ввод, если были нажаты определенные клавиши, то камера изменяется соответствующим образом.
Клавиши управления перемещаю камеру, Q и A увеличивают и уменьшают масштаб, W и E вращают камеру. Здесь есть несколько механизмов защиты, которые не позволяют камере выходить за границы мира.
Основным приложением для начальной загрузки обработчика является LWJGL приложение.
public class DesktopCameraController { public static void main(String[] args) { new LwjglApplication(new OrthographicCameraController(), "2D Camera", 480, 320, false); } }
В результате получается следующее приложение:
Большую часть времени нет нужны иметь доступ к свойствам камеры, так как наиболее распространенные сценарии покрыты следующими методами:
Методы и описание |
---|
lookAt(float x, float y, float z)
Пересчитывает направление камеры, чтобы камера смотрела на точку, определенную координатами по всем осям. Ось Z игнорируется для 2D. |
translate(float x, float y, float z)
Перемещает камеру на заданное значение по каждой оси. Обратите внимание, что ось Z игнорируется для |
rotate(float angle, float axisX, float axisY, float axisZ)
Вращает направление и вектор камеры по заданному углу вокруг заданных осей. Направление и вектор верха не будут ортогонализированы. Угол сохраняется, так что камера будет повернута на угол по отношению к своему предыдущему вращению. |
update()
Пересчитывает матрицы проекции и вида камера, а так же плоскость отсечения. |
apply(GL10 gl)
Устанавливает текущую матрицу проекции и вида модели камеры. Нужно вызывать после |
Комментариев нет:
Отправить комментарий