Калибровка 3d акселерометр для 2d игры - PullRequest
2 голосов
/ 14 марта 2012

Я делаю 2D игру.Телефон держится горизонтально, и персонаж двигается вверх / вниз и влево / вправо, чтобы избежать препятствий.Персонаж контролируется акселерометром на телефоне.Все работает нормально, если игрок не возражает против того, чтобы (0,0) (точка, в которой персонаж остановился) находился, когда телефон держится идеально ровно.В этом сценарии можно просто прочитать значения Y и X напрямую и использовать их для управления символом.Значения акселерометра находятся в диапазоне от -10 до 10 (они умножаются на константу ускорения для определения скорости движения персонажа), libgdx - это используемая структура.

Проблема в том, что (0,0) isnЭто не очень удобно, поэтому идея состоит в том, чтобы откалибровать его так, чтобы 0,0 было установлено в положение телефона в определенный момент времени.

Что приводит меня к моему вопросу, как бы я это сделал?Я попытался просто прочитать текущие значения X и Y, а затем вычесть их.Проблема заключается в том, что когда телефон удерживается под углом 90 градусов, значение смещения X равно 10 (что является максимальным значением), поэтому его становится невозможно переместить, поскольку значение никогда не превысит 10 (10-10 = 0).).Здесь как-то должна появиться ось Z, я просто не знаю, как.

Спасибо за помощь, я пытался объяснить как можно лучше, я пытался найти решение, но я не понимаюЯ даже не знаю, что означает то, что я ищу.

Ответы [ 2 ]

0 голосов
/ 06 марта 2014

Старый вопрос, но я даю ответ здесь, поскольку нигде не смог найти хорошего ответа для Android или LibGDX.Приведенный ниже код основан на решении, опубликованном для iOS (извините, я потерял ссылку).

Вы можете сделать это в трех частях:

  1. Capture aвектор, представляющий нейтральное направление:

    Vector3 tiltCalibration = new Vector3( 
                 Gdx.input.getAccelerometerX(), 
                 Gdx.input.getAccelerometerY(), 
                 Gdx.input.getAccelerometerZ() );
    
  2. Преобразовать этот вектор в матрицу вращения:

    public void initTiltControls( Vector3 tiltCalibration ) {
        Vector3.tmp.set( 0, 0, 1 );
        Vector3.tmp2.set( tiltCalibration ).nor();
        Quaternion rotateQuaternion = new Quaternion().setFromCross( Vector3.tmp, Vector3.tmp2 );
    
        Matrix4 m = new Matrix4( Vector3.Zero, rotateQuaternion, new Vector3( 1f, 1f, 1f ) );
        this.calibrationMatrix = m.inv();
    }
    
  3. Всякий раз, когда вам нужны входныеакселерометр, сначала пропустите их через матрицу вращения:

    public void handleAccelerometerInputs( float x, float y, float z ) {
    
        Vector3.tmp.set( x, y, z );
        Vector3.tmp.mul( this.calibrationMatrix );
    
        x = Vector3.tmp.x;
        y = Vector3.tmp.y;
        z = Vector3.tmp.z;
    
        [use x, y and z here]
        ...
    }
    
0 голосов
/ 15 марта 2012

Для простого решения вы можете посмотреть на методы:

Gdx.input.getAzimuth(), Gdx.input.getPitch(), Gdx.input.getRoll()

Недостатком является то, что те, кто так или иначе использует внутренний компас, чтобы дать вашим устройствам вращение по сравнению с севером / югом / востоком / западом.Я только очень скоро это проверил, так что я не уверен на 100% в этом.Возможно, стоит взглянуть.

Более сложный метод предполагает некоторую тригонометрию, в основном вы должны вычислить угол, под которым телефон удерживается, из Gdx.input.getAccelerometerX/Y/Z().Должно быть что-то вроде (для вращения вдоль длинной стороны телефона):

Math.atan(Gdx.input.getAccelerometerX() / Gdx.input.getAccelerometerZ());

Для обоих подходов вы сохраняете исходный угол и затем вычитаете его снова.Вы должны следить за диапазонами, хотя, я думаю, Math.atan(...) находится в пределах -Pi и Pi.

Надеюсь, это поможет вам как-то начать.Вы также можете выполнить поиск «Акселерометр для вращения / вращения / вращения» и т. П.

...