7 votes

Jeu Android Multitouch

Je suis actuellement en train de créer un jeu où l'utilisateur contrôle un navire avec un joystick à l'écran du côté gauche de l'écran et tire en tapant sur le côté droit de l'écran. Cependant, mes tentatives de multitouch ont été infructueuses. Lorsque l'utilisateur touche d'abord le joystick puis tire, cela fonctionne parfaitement, mais lorsque l'utilisateur touche le joystick en tirant, l'utilisateur n'est pas en mesure de faire glisser le joystick. Je suis encore novice en Android, donc toute aide serait grandement appréciée. Je vais coller le code ci-dessous.

@Override
public boolean onTouch(View v, MotionEvent event) {
    int action = event.getAction() & MotionEvent.ACTION_MASK;
    int pointerIndex=(event.getAction()&MotionEvent.ACTION_POINTER_ID_MASK) 
    >>MotionEvent.ACTION_POINTER_ID_SHIFT;
    int pI = event.getPointerId(pointerIndex);
    //Joystick à l'écran
    if(event.getX(pI)0&&event.getY(pI)<(screenHeight)&&event.getY(pI)>(screenHeight-(0.42*screenHeight))){
        sx2=event.getX(pI)-(stick.getWidth()/2);
        sy2=event.getY(pI);
        angle=(Math.atan2((sy2-sy),(sx2-sx)));
    }
    //Système de tir
    if(event.getX(pI)>screenWidth/3){
        switch(action){
        case MotionEvent.ACTION_DOWN:
            incrementRunnable.run();
            break;
        case MotionEvent.ACTION_POINTER_DOWN:
            incrementRunnable.run();
            break;
        case MotionEvent.ACTION_UP:
            handler.removeCallbacks(incrementRunnable);
            break;
        case MotionEvent.ACTION_POINTER_UP:
            handler.removeCallbacks(incrementRunnable);
            break;
        }

    }
    //réinitialiser le joystick
    if(event.getAction()==MotionEvent.ACTION_UP||event.getAction()==MotionEvent.ACTION_POINTER_UP){
        sx2=sx;
        sy2=sy;
        handler.removeCallbacks(incrementRunnable);
    }
    return true;
}

1voto

Louth Points 2943

Étant donné que vous pouvez manipuler le joystick et le bouton de tir de manière isolée, il est logique que vous obteniez correctement les dimensions de l'écran et que tout le reste concernant la détection de la proximité d'un pointeur à votre objet de jeu soit correct. J'ai lu des problèmes avec certaines versions d'Android et le multi touch mais supposons que ce n'est pas le problème.

La chose délicate avec un MotionEvent est qu'il est déclenché pour plusieurs pointeurs et que si vous vous intéressez aux touches et aux mouvements, vous devez considérer tous les pointeurs possibles. Je pense que le problème pourrait résider dans votre approche.

Plutôt que de déterminer ce que l'utilisateur touche et ensuite de comprendre quoi faire étant donné les différents types d'événements, vous devriez déterminer quel type d'événement se produit et ensuite déterminer avec quel objet l'utilisateur interagit. Cela rendra votre code un peu plus propre et facilitera la détection des problèmes à l'avenir.

J'ai pris votre exemple ci-dessus et l'ai réécrit comme indiqué ci-dessous. Cet exemple se contentera d'écrire du texte à l'écran pour montrer ce que et où l'utilisateur touche. Il peut déterminer les touches du joystick après le bouton de tir et vice versa.

MultiTouchGame.java

package com.droidhut.stackoverflow;

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.WindowManager;
import android.widget.TextView;

public class MultiTouchGame extends Activity implements OnTouchListener {
    StringBuilder builder = new StringBuilder();
    TextView textView;

    boolean[] joystickTouched = new boolean[10];
    boolean[] fireButtonTouched = new boolean[10];
    int joyX = 0;
    int joyY = 0;

    int screenHeight;
    int screenWidth;
    Pad pad = new Pad();

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        textView = new TextView(this);
        textView.setText("Touch and drag (multiple fingers supported)!");
        textView.setOnTouchListener(this);
        setContentView(textView);

        WindowManager mWinMgr = (WindowManager)getSystemService(Context.WINDOW_SERVICE);
        DisplayMetrics dm = new DisplayMetrics();
        mWinMgr.getDefaultDisplay().getMetrics(dm);
        screenHeight = dm.heightPixels;
        screenWidth = dm.widthPixels;

    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        int action = event.getAction() & MotionEvent.ACTION_MASK;
        int pointerIndex = (event.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
        int pI = event.getPointerId(pointerIndex);
        switch (action) {
            case MotionEvent.ACTION_DOWN:
            case MotionEvent.ACTION_POINTER_DOWN:
                joystickTouched[pI] = isPointerOnJoystick(event, pointerIndex);
                fireButtonTouched[pI] = isPointerOnFireButton(event, pointerIndex);
                break;
            case MotionEvent.ACTION_UP:        
            case MotionEvent.ACTION_POINTER_UP:
            case MotionEvent.ACTION_CANCEL:
                joystickTouched[pI] = false;
                fireButtonTouched[pI] = false;
                break;
            case MotionEvent.ACTION_MOVE:
                joystickTouched[pI] = isPointerOnJoystick(event, pointerIndex);
                fireButtonTouched[pI] = isPointerOnFireButton(event, pointerIndex);
                if (isTouchingJoystick()){
                    int index = getJoystickPointer();
                    if (index != -1 && index < event.getPointerCount()){
                        joyX = (int)event.getX(index);
                        joyY = (int)event.getY(index);
                    }
                }
                break;
        }

        updateTextView();       
        return true;
    }

    private boolean isPointerOnJoystick(MotionEvent event, int pointerIndex){
         return (event.getX(pointerIndex)0&&
                 event.getY(pointerIndex)<(screenHeight)&&event.getY(pointerIndex)>(screenHeight-(0.42*screenHeight)));
    }

    private boolean isPointerOnFireButton(MotionEvent event, int pointerIndex){
        return (event.getX(pointerIndex)>screenWidth/3);
    }

    private boolean isTouchingJoystick(){
        for (int i = 0; i < joystickTouched.length; i++){
            if (joystickTouched[i]){
                return true;
            }
        }
        return false;
    }

    private boolean isTouchingFireButton(){
        for (int i = 0; i < fireButtonTouched.length; i++){
            if (fireButtonTouched[i]){
                return true;
            }
        }
        return false;
    }

    private int getJoystickPointer(){
        for (int i = 0; i < joystickTouched.length; i++){
            if (joystickTouched[i]){
                return i;
            }
        }

        return -1;
    }

    private void updateTextView() {
        builder.setLength(0);
        builder.append(String.format("screenWidth[%d], screenHeight[%d]\n",screenWidth, screenHeight));
        builder.append(String.format("joystickTouched[%s]\n", isTouchingJoystick()));
        builder.append(String.format("fireButtonTouched[%s]\n", isTouchingFireButton()));
        builder.append(String.format("joystickMovement[%d,%d]",joyX,joyY));

        textView.setText(builder.toString());
    }

    private static class Pad {
      public int getWidth(){
        return 200;
      }
    }

}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X