J'ai passé d'innombrables heures à lire des tutoriels et à regarder toutes les questions liées à multiTouch d'ici et à Stackoverflow. Mais je n'arrive pas à comprendre comment le faire correctement. J'utilise une boucle pour obtenir mon pointerId
, je ne vois pas beaucoup de gens faire cela, mais c'est la seule façon que j'ai réussi à faire fonctionner quelque peu.
J'ai deux joysticks sur mon écran, un pour se déplacer et un pour contrôler la rotation de mes sprites et l'angle qu'il tire, comme dans Monster Shooter. Ces deux fonctionnent bien.
Mon problème est que lorsque je déplace mon sprite en même temps que la prise de vue Im, mon touchingPoint
pour mon mouvement est réglé sur celui touchingPoint
de ma prise de vue, car le x
et y
est plus haut sur la prise touchingPoint
de vue ( moving-stick
sur le côté gauche de l'écran, shooting-stick
sur le côté droit) , mon sprite accélère, cela crée un changement de vitesse indésirable pour mon sprite.
c'est ainsi que je l'ai résolu avec votre aide! c'est pour toute personne qui pourrait rencontrer un problème similaire:
public void update(MotionEvent event) {
if (event == null && lastEvent == null) {
return;
} else if (event == null && lastEvent != null) {
event = lastEvent;
} else {
lastEvent = event;
}
int action = event.getAction();
int actionCode = action & MotionEvent.ACTION_MASK;
int pid = action >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
int x = (int) event.getX(pid);
int y = (int) event.getY(pid);
int index = event.getActionIndex();
int id = event.getPointerId(index);
String actionString = null;
switch (actionCode)
{
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_POINTER_DOWN:
actionString = "DOWN";
try{
if(x > 0 && x < steeringxMesh + (joystick.get_joystickBg().getWidth() * 2)
&& y > yMesh - (joystick.get_joystickBg().getHeight()) && y < panel.getHeight()){
movingPoint.x = x;
movingPoint.y = y;
dragging = true;
draggingId = id;
}
else if(x > shootingxMesh - (joystick.get_joystickBg().getWidth()) && x < panel.getWidth()
&& y > yMesh - (joystick.get_joystickBg().getHeight()) && y < panel.getHeight()){
shootingPoint.x = x;
shootingPoint.y = y;
shooting=true;
shootingId=id;
}
}catch(Exception e){
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_OUTSIDE:
if(id == draggingId)
dragging = false;
if(id == shootingId)
shooting = false;
actionString = "UP";
break;
case MotionEvent.ACTION_MOVE:
for(index=0; index<event.getPointerCount(); index++) {
id=event.getPointerId(index);
int xx = (int) event.getX(index); //pro naming of variable
int yy = (int) event.getY(index);
if(dragging && id == draggingId) {
if(xx > 0 && xx < (steeringxMesh + joystick.get_joystickBg().getWidth() * 2)
&& yy > yMesh - (joystick.get_joystickBg().getHeight()) && yy < panel.getHeight()) {
movingPoint.x = xx;
movingPoint.y = yy;
}
else
dragging = false;
}
if(shooting && id == shootingId){
if(xx > shootingxMesh - (joystick.get_joystickBg().getWidth()) && xx < panel.getWidth()
&& yy > yMesh - (joystick.get_joystickBg().getHeight()) && yy < panel.getHeight()) {
shootingPoint.x = xx;
shootingPoint.y = yy;
}
else
shooting = false;
}
}
actionString = "MOVE";
break;
}
Log.d(TAG, "actionsString: " + actionString + ", pid: " + pid + ", x: " + x + ", y: " + y);
Je ne posterais pas autant de code si je n'étais pas à une perte absolue de ce que je fais mal. Je n'arrive tout simplement pas à bien comprendre le fonctionnement du multi-touch.
movingPoint
change fondamentalement pour mon premier et mon deuxième doigt. Je le lie à une boîte, mais aussi longtemps que je tiens un doigt dans cette boîte, il change sa valeur en fonction de l'endroit où mon deuxième doigt touche. Il se déplace dans la bonne direction et rien ne donne d'erreur, le problème est le changement de vitesse, c'est presque comme s'il additionne les deux points de contact.
Vous avez presque raison, mais vous devez utiliser votre identifiant de pointeur pour demander le X / Y au lieu de
i
Dans la documentation MotionEvent:
event.getX/Y
nécessitent un identifiant de pointeur, noni
, car il n'y a aucune garantie qu'ils seront dans le même ordre.De plus, il existe un autre problème subtil mais important. Remarquez comment la famille de fonctions getAction () ne prend pas de paramètre. C'est un peu bizarre, non? Obtenir X / Y nécessite l'ID du pointeur, mais pas l'action effectuée? Cela fait allusion à quelques éléments importants:
Cela signifie donc que vous recevez un appel vers votre gestionnaire tactile par action de pointeur (bas / déplacer / haut). Donc deux doigts en mouvement = 2 appels. Un effet secondaire désagréable de votre code est qu'il applique l'action d'un événement à tous les pointeurs ...
Ainsi, au lieu de parcourir les traces, obtenez simplement l'action pid / x / y / pour l'événement en cours uniquement (pour un mouvement simultané, vous obtiendrez un autre appel à votre gestionnaire un peu plus tard, comme je l'ai dit)
Voici mon code pour gérer les événements:
}
Pour revenir à votre code, vous devriez pouvoir le simplifier de la manière suivante. La boucle a disparu, sinon, si vous avez d'autres contraintes que vous n'avez pas mentionnées, vous pouvez toujours les rajouter. Il fonctionne en suivant quel identifiant de pointeur est utilisé pour quel contrôle (déplacer / tirer) lorsque DOWN est déclenché et en les réinitialisant sur UP. Puisque vous n'utilisez pas de gestes, vous pouvez restreindre votre commutateur () à DOWN, UP, MOVE et EXTERIEUR.
la source
sendTouchToGameEngine(pid, actionCode, (int)event.getX(pid), (int)event.getY(pid));
et quand vous l'appelez?int pid = action >> MotionEvent.ACTION_POINTER_ID_SHIFT;
eclipse me dit d'ajouter un supressWarning, est-ce normal? Désolé pour toutes les questions après une réponse aussi détaillée. MotionEvent est très nouveau pour moi et ne peut pas comprendre la logique pour une raison quelconquepid
, et la boucle est toujours là, ne fonctionnera pas sans, car j'ai besoin de l'obteniri
.Il y a un peu de bizarrerie avec ce code. Je n'utilise pas Android, alors peut-être que je pense que ce n'est pas le cas. Cependant, j'ai remarqué que vous obtenez le poste deux fois, de deux manières différentes:
D'abord, vous l'obtenez comme ceci au début de votre
pointerCount
boucle:Ensuite, à l'intérieur de votre instruction switch, vous obtenez ce qui suit:
Notez que vous passez de l'utilisation
i
à l'utilisationid
.Je suppose que c'est censé être l'ancienne méthode. Je recommande de remplacer toutes les instances de
(int) event.getX(id)
et d'utiliser la valeur quex
vous avez définie au début. De même, permuter(int) event.getY(id)
versy
.Essayez d'échanger ces parties:
Ensuite, à l'intérieur de votre commutateur, utilisez ceci:
la source
x
ety
, mais vous obtenez toujours la positionid
plus tard.x=event.getX(i)
), alorsx
devra stocker 2 valeurs chaque foispointerCount
est plus que 1, correct? Et ce dosnt se sent bien.event
c'est vraiment une liste d'événements. Vous accédez aux différents événements en parcourant la liste comme vous le faites. Donc, pour accéder à lax
position du deuxième événement que vous utilisezevent.getX(1)
(puisque nous commençons à 0). Il y a plusieursx
s, vous utilisez le paramètre pour lui dire lequel vous voulez. Vous parcourez tous les événements avec votrefor
boucle, alors utilisez ce numéro comme événement actuel qui vous intéresse. Voir ma suggestion de changement de code.J'ai eu un problème similaire une fois sur un Huawei U8150. Le multitouch à deux doigts sur cet appareil était vraiment mauvais, en utilisant une application de test multitouch (peut-être que c'était "Phone Tester" mais je ne suis pas sûr) J'ai pu voir que toucher avec le deuxième doigt déplaçait le 1er point de contact de plusieurs pixels . Si c'est votre problème, c'est lié au matériel et je ne pense pas que vous puissiez en faire beaucoup :(
Désolé pour mon mauvais anglais
la source
Je crois que votre problème est que vous supposez qu'entre les mises à jour, l'ordre dans lequel les pointeurs sont disposés reste le même. Ce ne sera probablement pas le cas.
Imaginez une situation où vous touchez avec le doigt A. Il y aura un pointeurCount () de 1, et A sera le seul élément que vous pouvez demander. Si vous ajoutez un deuxième doigt, le pointeurCount () sera 2, A sera à l'index 0, B sera à l'index 1. Si vous relevez le doigt A, pointerCount () sera à nouveau 1 et B sera à l'index 0 . Si vous touchez à nouveau avec le doigt A, A sera à l'index 1 et B sera à l'index 0 .
C'est pourquoi l'ID du pointeur est fourni, afin que vous puissiez suivre les contacts individuels entre les mises à jour. Donc, si la première touche du doigt B se voit attribuer l'ID 12, il aura toujours cet ID, même lorsque le doigt A est retiré et rajouté.
Donc, si votre code identifie une touche près de votre joystick de prise de vue, il doit vérifier s'il y a déjà une touche «prise de vue» en cours. Si ce n'est pas le cas, l'ID de la prise de vue doit être mémorisé dans une variable membre qui persiste jusqu'à la prochaine mise à jour. Dans les mises à jour suivantes, si vous avez une touche de `` prise de vue '' en cours, parcourez les pointeurs et recherchez le pointeur avec le bon ID, et c'est ce pointeur que vous devez utiliser pour suivre les mises à jour et tous les autres peuvent être ignorés. Idem pour la touche mouvement. Lorsque le toucher est relâché, vous effacez l'ID associé à ce joystick pour qu'un nouveau toucher puisse en prendre le contrôle.
Même si un toucher qui commence à proximité d'un joystick s'éloigne de la position de toucher d'origine, par son ID, vous pouvez toujours identifier correctement le joystick qu'il contrôle. Et comme bel effet secondaire, un deuxième doigt errant près d'un joystick particulier n'aura aucun effet, car le joystick sera lié au premier doigt qui l'a déclenché jusqu'à ce qu'il soit relâché.
la source