Files
SAE41_2025/src/main/java/sae/chuzzle/GestionnaireTactile.java
T

140 lines
4.1 KiB
Java

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