Попытка заставить два одновременных джойстика работать с сенсорными событиями

Два дня с этим бьюсь. Я использую игровой движок HTML5/JS под названием ImpactJS, и кто-то сделал очень полезный плагин для создания зон касания джойстика для мобильных устройств. Идея состоит в том, что вы указываете зону на экране, где джойстик активируется при касании этой области.

Код подключаемого модуля, который я использую, находится здесь< /а>. Я немного изменил его, добавив «curPos» (координаты x и y места, которого в данный момент касается пользователь), в остальном весь код идентичен. Я пытался решить эту проблему сам, а также связался с первоначальным создателем, но в настоящее время они, похоже, недоступны, и я ничего не получаю.

Я уверен, что здесь я делаю что-то очень неправильное, но хотя я могу заставить сенсорные зоны работать идеально сами по себе, каждый раз, когда я пытаюсь использовать оба джойстика одновременно, они частично перезаписывают друг друга.

Я указал две зоны следующим образом, когда моя игра инициализируется:

    this.joystick1 = new TouchJoystickZone(0, 0, ig.system.width / 2, ig.system.height);
    this.joystick2 = new TouchJoystickZone(ig.system.width / 2, 0, ig.system.width / 2, ig.system.height);

this.joystick1 отвечает за вращение игрока. this.joystick2 отвечает за ускорение игрока. В моем объекте Player у меня есть следующий код движения для двух джойстиков. Опять же, это отлично работает, когда у меня только один палец на экране/используется один джойстик:

            if( ig.ua.mobile ) {
            // ROTATION
            if (ig.game.joystick1.touchStart.x > 0 && ig.game.joystick1.touchStart.x < ig.system.width/2) {
                if (Math.abs(ig.game.joystick1.delta.x) >= 50 || Math.abs(ig.game.joystick1.delta.y) >= 50) {
                    this.joystickAngle = ig.game.Controller.toDegrees(ig.game.Controller.joystickAngle());
                    if (this.angle > this.joystickAngle + 20) {
                        this.angle -= this.turnSpeed * ig.system.tick;
                    }

                    else if (this.angle < this.joystickAngle - 20) {
                        this.angle += this.turnSpeed * ig.system.tick;
                    }

                    else {
                        this.angle = this.joystickAngle;
                    }
                } 
            }

            // THRUST
            if (ig.game.joystick2.touchStart.x > ig.system.width / 2) {
                if (ig.game.joystick2.delta.y <= -50) {
                    this.accel.x = Math.cos(this.angle*Math.PI/180)*this.thrust;
                    this.accel.y = (Math.sin(this.angle*Math.PI/180)*this.thrust);
                    this.fuel -= 0.1;
                }

                else if (ig.game.joystick2.delta.y >= 50) {
                    this.accel.x = Math.cos(this.angle*Math.PI/180)*-this.thrust;
                    this.accel.y = (Math.sin(this.angle*Math.PI/180)*-this.thrust);
                    this.fuel -= 0.1;
                }

            }

            else {
                this.accel.x = 0;
                this.accel.y = 0;
            }
        }

Однако, как только я кладу второй палец на экран, первый джойстик перезаписывается. Я могу вращаться, а затем двигаться или двигаться, а затем вращаться, и это работает нормально, но мне нужно делать и то, и другое одновременно.

Я обнаружил, что touchStart.x и touchStart.y, кажется, устанавливаются для обоих джойстиков, когда я нажимаю, чтобы использовать другой джойстик, а не только соответствующий джойстик1 или джойстик2, хотя в коде плагина эти координаты предназначены только для воздействия если касание этого джойстика находится в пределах указанной зоны. Я считаю, что это отчасти то, что способствует возникновению проблемы. На этом этапе я потратил часы, пытаясь понять это, и так же потерян, как и в начале.

Может ли кто-нибудь указать мне правильное направление с использованием обоих этих джойстиков одновременно?


person spectralbat    schedule 23.10.2012    source источник
comment
я думаю, что это невозможно в javascript, потому что он не является многопоточным, чтобы обрабатывать это параллельно   -  person Memos Electron    schedule 23.10.2012
comment
На каком устройстве вы его тестируете? - Поддерживает ли это устройство мультитач, кроме захвата/вращения?   -  person Rob Hardy    schedule 23.10.2012
comment
Извините, я забыл упомянуть детали устройства. Я тестирую на iPhone 4, компилируя в Xcode с помощью Ejecta и развертывая на iOS (которую этот плагин якобы поддерживает и на самом деле предназначен). Multitouch упоминается в сообщении на форуме создателя — есть одна известная ошибка, связанная с тем, что он не регистрируется, но, по-видимому, это применимо только в том случае, если я одновременно использую другой конкретный плагин, чего я не делаю.   -  person spectralbat    schedule 23.10.2012
comment
@memosdp Разве для этого нельзя использовать рабочих? Основной поток требуется только для доступа к DOM, верно?   -  person Constantino Tsarouhas    schedule 02.03.2013


Ответы (2)


Сценарий джойстика, который вы используете, ищет только первый палец. Далее строки 47-48.

    var x = ev.touches[0].pageX - pos.left,
        y = ev.touches[0].pageY - pos.top;

«0» определяет, какой палец отслеживать.

Сценарий будет изменен, чтобы знать, какой палец находится на каком элементе, а затем отслеживать только этот палец. Вы можете сделать это, либо определив, какой элемент был нажат первым, либо по местоположению.

Пример JSFiddle: http://jsfiddle.net/7WR88/5/

http://www.sitepen.com/blog/2008/07/10/touching-and-gesturing-on-the-iphone/

person Dcullen    schedule 23.10.2012
comment
Дело в том, что я думал, что, поскольку я создаю два экземпляра этого объекта (один для джойстика1 и другой для джойстика2), каждый раз, когда используется ev, он относится только к касаниям, которые относятся к этому конкретному джойстику. Разве это не так? (Я заметил, что если я помещу два пальца в каждую зону джойстика, то и joystick1.startTouch.x, и joystick2.startTouch.x имеют значения, а не 0, значения просто идентичны координате x второго касания). - person spectralbat; 23.10.2012
comment
Если другой палец уже нажат, когда вы нажимаете на вторую область, другой палец коснется первым. Сложность в том, что это работает и в обратную сторону. Первое касание – это уже нажатое. Я попытаюсь получить пример в jsfiddle. - person Dcullen; 23.10.2012
comment
jsfiddle.net/7WR88/5 Вы можете увидеть в этом jsfiddle на iPhone, если вы нажмете один каждым пальцем регистрируется по 2 прикосновения к каждому. - person Dcullen; 23.10.2012
comment
Спасибо за разъяснения! Однако означает ли это, что мне вообще нет смысла создавать джойстик1 и джойстик2 в моей инициализации? Я также напечатал длину ev.touches на консоли и постоянно получаю «1», независимо от того, опустил ли я два пальца или один (за исключением странного случая, когда сначала нажимаю еще раз, иногда появляется сообщение « 2' на несколько кадров, затем возвращается к 1). Однако координаты startTouch обоих джойстиков по-прежнему регистрируются (за исключением того, что они оба становятся идентичными при втором касании) - - person spectralbat; 23.10.2012
comment
- Я просто не уверен, почему плагину потребовалась такая большая модификация, когда он якобы был разработан для мультитач на iOS с этим движком. Я просто предположил, что это было связано с тем, что я использовал его неправильно. - person spectralbat; 23.10.2012
comment
Нет, вроде все сделал правильно. Может быть, представить вопрос, и он может добавить функциональность. Проект кажется совсем недавно созданным. Извини! - person Dcullen; 24.10.2012

Как упоминал @Dcullen, в каждом событии может быть несколько касаний, начиная с первого касания.

Было бы простым решением перебрать коллекцию ev.touches и посмотреть, попадает ли каждое касание в горячую зону. Если он попадает в активную зону 1, рассматривайте его как прикосновение к джойстику 1. Если он попадает в активную зону 2, рассматривайте его как прикосновение к джойстику 2.

Это означало бы, что не имеет значения, в каком порядке появляются касания, потому что они всегда будут отображаться на правильный джойстик, если они находятся рядом с ним.

person Rob Hardy    schedule 24.10.2012