Системные различия в системе libgdx между рендерингом и сенсорным вводом
У меня есть экран (BaseScreen реализует интерфейс Screen), который отображает PNG-изображение. При щелчке по экрану он перемещает символ в позицию, затронутую (для целей тестирования).
public class DrawingSpriteScreen extends BaseScreen {
private Texture _sourceTexture = null;
float x = 0, y = 0;
@Override
public void create() {
_sourceTexture = new Texture(Gdx.files.internal("data/character.png"));
}
.
.
}
Во время рендеринга экрана, если пользователь коснулся экрана, я захватил координаты касания, а затем использовал их для визуализации изображения символа.
@Override
public void render(float delta) {
if (Gdx.input.justTouched()) {
x = Gdx.input.getX();
y = Gdx.input.getY();
}
super.getGame().batch.draw(_sourceTexture, x, y);
}
Проблема заключается в том, что координаты для рисования изображения начинаются с нижнего левого положения (как указано в вики-библиотеке LibGDX), а координаты для ввода касания начинаются с верхнего левого угла. Поэтому проблема, с которой я сталкиваюсь, заключается в том, что я нажимаю на нижнюю правую сторону, она перемещает изображение в верхнем правом углу. Мои координаты могут быть X 675 Y 13, которые при касании будут находиться в верхней части экрана. Но символ отображается внизу, так как координаты начинаются с левого нижнего положения.
Почему? Почему системы координат обращаются вспять? Я использую неправильные объекты для определения этого?
Ответы
Ответ 1
Для обнаружения столкновения я использую camera.unproject(vector3)
. Я установил vector3
как:
x = Gdx.input.getX();
y = Gdx.input.getY();
z=0;
Теперь я передаю этот вектор в camera.unproject(vector3)
. Используйте x
и y
этого вектора для рисования вашего символа.
Ответ 2
Вы делаете это правильно. Libgdx обычно предоставляет системы координат в своем "родном" формате (в этом случае - собственные координаты сенсорного экрана и координаты по умолчанию OpenGL). Это не создает никакой согласованности, но это означает, что библиотека не должна находиться между вами и всем остальным. В большинстве игр OpenGL используется камера, которая отображает на экране относительно произвольные "мировые" координаты, поэтому координаты мира/игры часто сильно отличаются от координат экрана (поэтому согласованность невозможна). См. Изменение системы координат в LibGDX (Java)
Есть два способа обойти это. Один из них преобразует ваши сенсорные координаты. Другой - использовать другую камеру (другую проекцию).
Чтобы зафиксировать координаты касания, просто вычтите y из высоты экрана. Это немного взломать. В более общем плане вы хотите "непроектировать" с экрана в мир (см.
Camera.unproject()
варианты). Это, наверное, самый простой.
В качестве альтернативы исправить камеру см. "Изменение системы координат в LibGDX (Java) "или этот пост на форуме libgdx. В основном вы определяете пользовательскую камеру, а затем устанавливаете SpriteBatch
для использования, а не по умолчанию.:
// Create a full-screen camera:
camera = new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
// Set it to an orthographic projection with "y down" (the first boolean parameter)
camera.setToOrtho(true, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
camera.update();
// Create a full screen sprite renderer and use the above camera
batch = new SpriteBatch(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
batch.setProjectionMatrix(camera.combined);
В то время как фиксация камеры работает, она немного "плавает вверх по течению". Вы столкнетесь с другими рендерами (ShapeRenderer
, рендерерами шрифтов и т.д.), Которые также будут по умолчанию "неправильной" камерой и должны быть исправлены.
Ответ 3
У меня была такая же проблема, я просто сделал это.
public boolean touchDown(int screenX, int screenY, int pointer, int button) {
screenY = (int) (gheight - screenY);
return true;
}
и каждый раз, когда вы хотите вводить данные от пользователя, не используйте Gdx.input.getY();
вместо этого используйте (Gdx.graphics.getHeight() - Gdx.input.getY())
это сработало для меня.
Ответ 4
В приведенной ниже ссылке обсуждается эта проблема.
Проецирует данные координаты в мировом пространстве для отображения координат.
Вам нужно использовать метод project(Vector3 worldCoords)
в классе com.badlogic.gdx.graphics.Camera
.
private Camera camera;
............
@Override
public boolean touchDown(int screenX, int screenY, int pointer, int button) {
Создайте экземпляр вектора и инициализируйте его с помощью координат обработчика входных событий.
Vector3 worldCoors = new Vector3(screenX, screenY, 0);
Проекты worldCoors, заданные в мировом пространстве для отображения координат.
camera.project(worldCoors);
Использование прогнозируемых координат.
world.hitPoint((int) worldCoors.x, (int) worldCoors.y);
OnTouch();
return true;
}