Dúvida sobre MultiTouch

Olá a todos!

Existe um livro da Appess chamado “Beggining Android 4 game development”

http://books.google.com.br/books?id=eteY_yd3N5cC&pg=PA216&lpg=PA216&dq=%22if+(event.getAction()+!%3D+MotionEvent.ACTION_MOVE+%26%26+i+!%3D+pointerIndex)%22&source=bl&ots=A6wzsQFgW5&sig=LxCqlCIDquousBd0C7RDzp5x180&hl=pt-BR&sa=X&ei=_P2EUNbjO4O08AT4lYC4Bg&ved=0CB8Q6AEwAA#v=onepage&q=%22if%20(event.getAction()%20!%3D%20MotionEvent.ACTION_MOVE%20%26%26%20i%20!%3D%20pointerIndex)%22&f=false

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?

Oi,

Só tem isso de código? Provavelmente deva ter um else ou um for sobre ele.

Nesse código ele está forçando a repetição do laço caso o movimento feito pelo touch não seja o correto.

Tchauzin!

Oi lina…

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…

Dá uma olhadinha la e me diga o que você acha.

Posso passar o código comentado para ajudar:

[code]public boolean onTouch(View v, MotionEvent event) {
synchronized (this) {

	//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;
}

}[/code]

Oi,

Desculpe! Não tinha vista o LINK postado =)

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…

Tchauzin!

Cara, ai é que está o jogo!

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

E ai, descobriram alguma coisa?

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.

Olá Marky…

Não entendi muito bem o que você quis dizer. Poderia me dar um exemplo?

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.

Ah sim, ja joguei =)

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.

huuuuummm…

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.

Peguei o raciocínio?

Olá
Se a ação não for ACTION_MOVE ele só vai processar o ponto tocado, e ignorar os outros pontos.

Olá Gusukuma,

Você diz isso com base somente na condição? Por que ele ignoraria os demais pontos?

Somente na condição.
Teria sentido tratar os outros pontos? Isso depende dos requisitos da lógica do game

Bem, mas e como o código passaria dessa condição para registrar eventos de touch DOWN e UP?

Afinal, os eventos precisam ser inicializados antes de serem tratados a partir somente do movimento

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

[quote=Rafagan Abreu]huuuuummm…

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.

Peguei o raciocínio?[/quote]

É isso mesmo.