package sae.chuzzle; import android.view.MotionEvent; import android.view.View; public class GestionnaireTactile implements View.OnTouchListener { private static final int NB_LIGNES = EtatJeu.NB_LIGNES; private static final int NB_COLONNES = EtatJeu.NB_COLONNES; private static final float SEUIL_DIRECTION_PX = 10f; private final VueGrille vueGrille; private final EtatJeu etatJeu; private final Controleur controleur; private float touchDebutX, touchDebutY; private int ligneTouchee, colonneTouchee; private Boolean estLigne; private int indexGlissement; private float decalagePx; private float tailleCase; public GestionnaireTactile(VueGrille vueGrille, EtatJeu etatJeu, Controleur controleur) { this.vueGrille = vueGrille; this.etatJeu = etatJeu; this.controleur = controleur; } @Override public boolean onTouch(View v, MotionEvent event) { if (etatJeu.estTerminee()) { return false; } switch (event.getAction()) { case MotionEvent.ACTION_DOWN: tailleCase = calculerTailleCase(); gererDebut(event); return true; case MotionEvent.ACTION_MOVE: gererMouvement(event); return true; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: gererFin(event.getAction() == MotionEvent.ACTION_UP); return true; } return false; } private void gererDebut(MotionEvent event) { touchDebutX = event.getX(); touchDebutY = event.getY(); estLigne = null; decalagePx = 0f; float margeGauche = (vueGrille.getWidth() - tailleCase * NB_COLONNES) / 2f; float margeHaut = (vueGrille.getHeight() - tailleCase * NB_LIGNES) / 2f; ligneTouchee = (int) ((touchDebutY - margeHaut) / tailleCase); colonneTouchee = (int) ((touchDebutX - margeGauche) / tailleCase); ligneTouchee = Math.max(0, Math.min(NB_LIGNES - 1, ligneTouchee)); colonneTouchee = Math.max(0, Math.min(NB_COLONNES - 1, colonneTouchee)); } private void gererMouvement(MotionEvent event) { float dx = event.getX() - touchDebutX; float dy = event.getY() - touchDebutY; if (estLigne == null) { if (Math.abs(dx) > SEUIL_DIRECTION_PX || Math.abs(dy) > SEUIL_DIRECTION_PX) { estLigne = Math.abs(dx) >= Math.abs(dy); if (estLigne) { indexGlissement = ligneTouchee; } else { indexGlissement = colonneTouchee; } } else { return; } } if (estLigne) { decalagePx = dx; } else { decalagePx = dy; } // Affiche le glissement réel du doigt (permet la rotation multi-cases) vueGrille.definirGlissement(estLigne, indexGlissement, decalagePx); } private void gererFin(boolean estRelachement) { if (estLigne == null) { vueGrille.annulerGlissement(); return; } if (tailleCase <= 1f) { vueGrille.annulerGlissement(); estLigne = null; return; } // Arrondi au nombre de cases le plus proche (permet ±1, ±2, ±3…) int nbCases = (int) Math.round(decalagePx / tailleCase); if (nbCases != 0 && estRelachement) { boolean accepte = etatJeu.appliquerCoup(estLigne, indexGlissement, nbCases); if (accepte) { controleur.rafraichirAffichage(); controleur.verifierFinDePartie(); } } vueGrille.annulerGlissement(); estLigne = null; } private float calculerTailleCase() { float l = vueGrille.getWidth(); float h = vueGrille.getHeight(); if (l == 0 || h == 0) { return 1f; } return Math.min(l / NB_COLONNES, h / NB_LIGNES); } }