Eu realmente não estou conseguindo entender o que significa a linha de código:
if (event.getAction() != MotionEvent.ACTION_MOVE && i != pointerIndex) {
// if it's an up/down/cancel/out event, mask the id to see if we should process it for this touch point
continue;
}
Alguém que já tenha estudado o livro ou que já implementou multitouch poderia me esclarecer?
Na verdade, esse é o trecho do código que eu não estou entendendo. O código total pode ser visto no link que passei.
Lá, basicamente ele processa cada multitouch dentro do método onTouch. Se você der uma olhada, vai perceber que a variável pointerIndex somente é usada nesse trecho do código. E segundo o que ele diz no texto, ela deveria representar o próprio ID do touch atual, o que na verdade não acontece, pois capturamos o ID do touch recebido a partir do i no laço…
//Captura o valor to tipo do evento, removendo informações do indice
int action = event.getAction() & MotionEvent.ACTION_MASK;
//Captura o indice do touch(qual é o inteiro que representa o dedo na tela que trataremos o evento)
int pointerIndex = (event.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) >>
MotionEvent.ACTION_POINTER_INDEX_SHIFT;
//Calcula quantos eventos existem em um touch
int pointerCount = event.getPointerCount();
//Processamos os eventos para cada um dos touchPoints. 'i' representará o ponto que estamos processando
TouchEvent touchEvent;
for (int i = 0; i < MAX_TOUCHPOINTS; i++) {
//Caso o número de pontos pressionados na tela for menor que o nosso ponto em questão, então o zeramos
if (i >= pointerCount) {
isTouched[i] = false;
id[i] = -1;
continue;
}
//Retorna o ID para este ponto
int pointerId = event.getPointerId(i);
//??????????
if (event.getAction() != MotionEvent.ACTION_MOVE && i != pointerIndex) {
// if it's an up/down/cancel/out event, mask the id to see if we should process it for this touch
// point
continue;
}
switch (action) {
case MotionEvent.ACTION_DOWN: //Trata eventos de toque para single touch
case MotionEvent.ACTION_POINTER_DOWN: //Trata eventos de toque para multi touch
touchEvent = touchEventPool.newObject();
touchEvent.type = TouchEvent.TOUCH_DOWN; //Tipo do evento
touchEvent.pointer = pointerId; //id do touch
touchEvent.x = touchX[i] = (int) (event.getX(i) * scaleX); //Posições
touchEvent.y = touchY[i] = (int) (event.getY(i) * scaleY);
isTouched[i] = true; //Estado atual do touch para esse ponto
id[i] = pointerId; //Controle para mais tarde ao recebermos a requisição de um dado num ponto descobrirmos se ele ainda existe
touchEventsBuffer.add(touchEvent);
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
case MotionEvent.ACTION_CANCEL:
touchEvent = touchEventPool.newObject();
touchEvent.type = TouchEvent.TOUCH_UP;
touchEvent.pointer = pointerId;
touchEvent.x = touchX[i] = (int) (event.getX(i) * scaleX);
touchEvent.y = touchY[i] = (int) (event.getY(i) * scaleY);
isTouched[i] = false;
id[i] = -1; //Marcamos o ponto com -1 para informar que ele não existe mais
touchEventsBuffer.add(touchEvent);
break;
case MotionEvent.ACTION_MOVE:
touchEvent = touchEventPool.newObject();
touchEvent.type = TouchEvent.TOUCH_DRAGGED;
touchEvent.pointer = pointerId;
touchEvent.x = touchX[i] = (int) (event.getX(i) * scaleX);
touchEvent.y = touchY[i] = (int) (event.getY(i) * scaleY);
isTouched[i] = true;
id[i] = pointerId;
touchEventsBuffer.add(touchEvent);
break;
}
}
return true;
}
Então, pelo que pude analisar você não pode pegar o pointer pelo ‘i’ do FOR. Até porque o ‘i’ do for é uma variável contadora e possivelmente não representa (de forma alguma) o ID do touch atual.
Ao meu ver, o código abaixo está errado:
Deveria ser algo do tipo:
Provavelmente, o pointerIndex deverá ser “atualizado” pelo FOR, mas isso já é uma outra coisa que pode ou não ser verdade…
Esse livro é uma versão atualizada de um livro mais antigo chamado “Beggining Android Games”, e nesse livro, a solução para este problema do multitouch leva como consideração o pointerIndex como valor de índice…
Eu realmente não testei o código do livro antigo para ver, mas esse código desse livro é totalmente funcional, eu mesmo testei. Então a lógica não está errada.
Agora eu não sei por quê os caras mudaram a solução na versão nova pra essa
Cada dedo que voce toca na tela dispara um evento e a cada dedo (ou ponteiro) é associado a um id, voce pode guarda-los para manter o track de todo o movimento.
Dentro de um mesmo MotionEvent voce consegue pegar o estado de todos os ponteiros através do id dele.
Um exemplo seria que nem o Fruit Ninja (se nao conheçe: baixe-o) voce pode tocar quantos dedos quiser na tela e fazer movimento para cortar as frutas, a maneira de saber qual dedo se movimentou para onde é guardar cada pointerId para acompanhar os movimentos.
Então, pensando nisso, porque ele está desviando o loop para a próxima iteração caso algo como isso aconteça?
Como pode event.getAction() != MotionEvent.ACTION_MOVE && i != pointerIndex indicar “guardar pointerId para acompanhar os movimentos se estiverem ocorrendo”, se a primeira condição do if é evitar que o mesmo seja processado, caso o tipo do evento seja ACTION_MOVE?
Por que se voce tiver com dois dedos na tela, um deles se mover, o onTouch será invocado, onde o ponteiro de um vai continuar parado e seu action não será ACTION_MOVE e o outro vai.
Então essa condição basicamente serve para ignorar touchs na tela que já foram processados, mas que permaneceram na mesma condição, e então passar a processar os touchs que foram modificados no caso com Action Move.
Creio que está misturando o conceito de movimento do jogador com o evento do game
Cada movimento do jogador gera evento(s) no app, que são diferenciados de acordo com as diferentes atitudes do jogador
Um toque, manter o dedo pressionado, deslizar sobre a tela, etc
Então essa condição basicamente serve para ignorar touchs na tela que já foram processados, mas que permaneceram na mesma condição, e então passar a processar os touchs que foram modificados no caso com Action Move.