Системные различия в системе 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;
}