Relecture + Ajustement

This commit is contained in:
2026-03-29 20:41:19 +02:00
parent 1692cd0ba3
commit a7deb9f726
9 changed files with 186 additions and 68 deletions
+22 -14
View File
@@ -7,13 +7,12 @@ import android.widget.Button;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
public class Controleur { public class Controleur implements View.OnClickListener {
private final Activity activite; private final Activity activite;
private final EtatJeu etatJeu; private final EtatJeu etatJeu;
private final VueGrille vueGrille; private final VueGrille vueGrille;
private final long graine; private final long graine;
private final TextView tvScore; private final TextView tvScore;
private final TextView tvCoups; private final TextView tvCoups;
@@ -30,9 +29,6 @@ public class Controleur {
public Controleur(Activity activite, EtatJeu etatJeu, VueGrille vueGrille, public Controleur(Activity activite, EtatJeu etatJeu, VueGrille vueGrille,
long graine, TextView tvScore, TextView tvCoups, long graine, TextView tvScore, TextView tvCoups,
boolean hardMode) { boolean hardMode) {
this.activite = activite; this.activite = activite;
this.etatJeu = etatJeu; this.etatJeu = etatJeu;
this.vueGrille = vueGrille; this.vueGrille = vueGrille;
@@ -49,17 +45,21 @@ public class Controleur {
this.layoutCles = activite.findViewById(R.id.layoutCles); this.layoutCles = activite.findViewById(R.id.layoutCles);
this.btnReinitialisationObjectif = activite.findViewById(R.id.btnReinitialisationObjectif); this.btnReinitialisationObjectif = activite.findViewById(R.id.btnReinitialisationObjectif);
if (tvObjectif != null) tvObjectif.setVisibility(View.VISIBLE); if (tvObjectif != null) {
if (tvNbObjectifs != null) tvNbObjectifs.setVisibility(View.VISIBLE); tvObjectif.setVisibility(View.VISIBLE);
if (layoutCles != null) layoutCles.setVisibility(View.VISIBLE); }
if (tvNbObjectifs != null) {
tvNbObjectifs.setVisibility(View.VISIBLE);
}
if (layoutCles != null) {
layoutCles.setVisibility(View.VISIBLE);
}
if (btnReinitialisationObjectif != null) { if (btnReinitialisationObjectif != null) {
btnReinitialisationObjectif.setOnClickListener(v -> reinitialiserObjectif()); btnReinitialisationObjectif.setOnClickListener(this);
} }
} }
rafraichirAffichage(); rafraichirAffichage();
} }
@@ -86,8 +86,8 @@ public class Controleur {
*/ */
public void gererFinDeCoup() { public void gererFinDeCoup() {
// 1 clé tous les 5 coups // 1 clé tous les 4 coups
if (hardMode && etatJeu.obtenirNbCoups() % 5 == 0) { if (hardMode && etatJeu.obtenirNbCoups() % 4 == 0) {
gestionnaireObjectifs.ajouterCle(); gestionnaireObjectifs.ajouterCle();
} }
// --- Logique Hard Mode // --- Logique Hard Mode
@@ -120,7 +120,7 @@ public class Controleur {
} }
/** /**
* Tente de réinitialiser l'objectif en cours en consommant 3 clés. * Réinitialiser l'objectif en cours si la clé est consommé.
* Affiche un Toast si le joueur n'a pas assez de clés. * Affiche un Toast si le joueur n'a pas assez de clés.
*/ */
public void reinitialiserObjectif() { public void reinitialiserObjectif() {
@@ -167,6 +167,14 @@ public class Controleur {
} }
} }
@Override
public void onClick(View v) {
if (v.getId() == R.id.btnReinitialisationObjectif) {
reinitialiserObjectif();
}
}
public void rafraichirAffichage() { public void rafraichirAffichage() {
tvScore.setText("Score : " + etatJeu.obtenirScore()); tvScore.setText("Score : " + etatJeu.obtenirScore());
tvCoups.setText("Coups : " + etatJeu.obtenirNbCoups()); tvCoups.setText("Coups : " + etatJeu.obtenirNbCoups());
+36 -3
View File
@@ -6,15 +6,13 @@ import java.util.Random;
/** /**
* Gère la session de jeu (score, coups, état de la partie) et délègue la * Gère la session de jeu (score, coups, état de la partie) et délègue la
* manipulation * manipulation des pièces de la grille à la classe Plateau.
* physique de la grille à la classe Plateau.
*/ */
public class EtatJeu { public class EtatJeu {
private final Plateau plateau; private final Plateau plateau;
private final Random aleatoire; private final Random aleatoire;
private final boolean hardMode; private final boolean hardMode;
private int score = 0; private int score = 0;
private int nbCoups = 0; private int nbCoups = 0;
private boolean partieTerminee = false; private boolean partieTerminee = false;
@@ -49,6 +47,11 @@ public class EtatJeu {
return plateau.copierGrille(); return plateau.copierGrille();
} }
/**
* Retourne l'état des verrous (cases bloquées)
* On crée une copie pour que personne ne puisse modifier les verrous
* directement sans passer par les règles de cette classe
*/
public boolean[][] obtenirVerrous() { public boolean[][] obtenirVerrous() {
// Copie manuelle pour respecter l'encapsulation // Copie manuelle pour respecter l'encapsulation
boolean[][] v = plateau.getVerrous(); boolean[][] v = plateau.getVerrous();
@@ -61,6 +64,10 @@ public class EtatJeu {
// --- Actions // --- Actions
/**
* Tente de déplacer une ligne ou une colonne.
* Si le mouvement ne crée aucune série de 3 couleurs, il est annulé.
*/
public boolean appliquerCoup(boolean estLigne, int index, int sens) { public boolean appliquerCoup(boolean estLigne, int index, int sens) {
if (partieTerminee || plateau.estBloque(estLigne, index)) { if (partieTerminee || plateau.estBloque(estLigne, index)) {
return false; return false;
@@ -93,6 +100,10 @@ public class EtatJeu {
return true; return true;
} }
/**
* Gère les "cascades" : quand des pièces disparaissent, d'autres tombent
* et peuvent créer de nouvelles séries automatiquement.
*/
private int resoudreCascades() { private int resoudreCascades() {
int baseTotal = 0; int baseTotal = 0;
int nbSeriesTotal = 0; int nbSeriesTotal = 0;
@@ -176,6 +187,9 @@ public class EtatJeu {
return new int[] { pts, count }; return new int[] { pts, count };
} }
/**
* Définit combien de points rapporte une série selon sa taille (3, 4, 5...).
*/
private int pointsPourLongueur(int n) { private int pointsPourLongueur(int n) {
if (n == 3) if (n == 3)
return 8; return 8;
@@ -186,6 +200,10 @@ public class EtatJeu {
return 64; return 64;
} }
/**
* Transforme une liste de positions en une "carte" (masque) de la grille
* pour savoir rapidement quelles cases doivent être supprimées.
*/
private boolean[][] creerMasque(List<int[]> positions) { private boolean[][] creerMasque(List<int[]> positions) {
boolean[][] m = new boolean[Plateau.NB_LIGNES][Plateau.NB_COLONNES]; boolean[][] m = new boolean[Plateau.NB_LIGNES][Plateau.NB_COLONNES];
for (int[] p : positions) { for (int[] p : positions) {
@@ -200,6 +218,10 @@ public class EtatJeu {
} }
} }
/**
* Parcourt l'intégralité des possibilités pour vérifier si le joueur
* peut encore effectuer au moins un mouvement créant une série.
*/
public boolean aUnCoupValide() { public boolean aUnCoupValide() {
for (int i = 0; i < Plateau.NB_LIGNES; i++) { for (int i = 0; i < Plateau.NB_LIGNES; i++) {
if (plateau.estBloque(true, i)) { if (plateau.estBloque(true, i)) {
@@ -224,6 +246,10 @@ public class EtatJeu {
return false; return false;
} }
/**
* Simule un déplacement pour voir s'il créerait une série,
* sans modifier la "vraie" grille de jeu du joueur.
*/
private boolean simulerCoup(boolean estLigne, int idx, int s) { private boolean simulerCoup(boolean estLigne, int idx, int s) {
int[][] save = plateau.copierGrille(); int[][] save = plateau.copierGrille();
if (estLigne) { if (estLigne) {
@@ -236,10 +262,14 @@ public class EtatJeu {
return ok; return ok;
} }
public void forcerFinDePartie() { public void forcerFinDePartie() {
partieTerminee = true; partieTerminee = true;
} }
/**
* Prépare les données du jeu pour les sauvegarder (en cas de fermeture de l'app).
*/
public void sauvegarderEtat(Bundle b) { public void sauvegarderEtat(Bundle b) {
int[] g = new int[36]; int[] g = new int[36];
boolean[] v = new boolean[36]; boolean[] v = new boolean[36];
@@ -258,6 +288,9 @@ public class EtatJeu {
b.putBoolean("partieTerminee", partieTerminee); b.putBoolean("partieTerminee", partieTerminee);
} }
/**
* Recharge les données du jeu sauvegardées précédemment.
*/
public void restaurerEtat(Bundle b) { public void restaurerEtat(Bundle b) {
if (!b.containsKey("grille")) return; if (!b.containsKey("grille")) return;
@@ -29,7 +29,7 @@ public class GestionnaireObjectifs {
// N (nbSeriesCible) tel que M - N >= 1 et N <= 3. // N (nbSeriesCible) tel que M - N >= 1 et N <= 3.
for (int m = 2; m <= 5; m++) { for (int m = 2; m <= 5; m++) {
for (int n = 1; n <= m - 1 && n <= 3; n++) { for (int n = 1; n <= m - 1 && n <= 3; n++) {
// Probabilité inversement proportionnelle à la facilité (M-N). // Plus l'objectif offre une marge de coups importante (M-N), plus il a de chances de tomber.
// Plus (M-N) est petit, plus c'est dur. // Plus (M-N) est petit, plus c'est dur.
int diff = m - n; int diff = m - n;
int poids = diff * diff; // On utilise le carré pour accentuer la différence de probabilité int poids = diff * diff; // On utilise le carré pour accentuer la différence de probabilité
@@ -99,4 +99,3 @@ public class GestionnaireObjectifs {
} }
} }
} }
@@ -3,21 +3,28 @@ package sae.chuzzle;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.View; import android.view.View;
/**
* Gère les interactions tactiles sur la grille de jeu.
* Traduit les mouvements de doigt en déplacements de lignes ou colonnes.
*/
public class GestionnaireTactile implements View.OnTouchListener { public class GestionnaireTactile implements View.OnTouchListener {
private static final int NB_LIGNES = Plateau.NB_LIGNES; private static final int NB_LIGNES = Plateau.NB_LIGNES;
private static final int NB_COLONNES = Plateau.NB_COLONNES; private static final int NB_COLONNES = Plateau.NB_COLONNES;
// Distance minimale (en pixels) avant de décider si le joueur déplace une ligne ou une colonne.
// Cela évite les déclenchements accidentels lors d'un simple clic.
private static final float SEUIL_DIRECTION_PX = 10f; private static final float SEUIL_DIRECTION_PX = 10f;
private final VueGrille vueGrille; private final VueGrille vueGrille;
private final EtatJeu etatJeu; private final EtatJeu etatJeu;
private final Controleur controleur; private final Controleur controleur;
private float touchDebutX, touchDebutY; private float touchDebutX, touchDebutY; // Position initiale du doigt
private int ligneTouchee, colonneTouchee; private int ligneTouchee, colonneTouchee; // Indices de la case située sous le doigt au départ
private Boolean estLigne; private Boolean estLigne; // null = direction inconnue, true = horizontal, false = vertical
private int indexGlissement; private int indexGlissement; // Numéro de la ligne ou colonne que l'on fait glisser
private float decalagePx; private float decalagePx; // Distance parcourue par le doigt depuis le début
private float tailleCase; private float tailleCase;
public GestionnaireTactile(VueGrille vueGrille, public GestionnaireTactile(VueGrille vueGrille,
@@ -61,12 +68,15 @@ public class GestionnaireTactile implements View.OnTouchListener {
estLigne = null; estLigne = null;
decalagePx = 0f; decalagePx = 0f;
// Calcule le décalage pour que le doigt vise bien les cases centrées
float margeGauche = (vueGrille.getWidth() - tailleCase * NB_COLONNES) / 2f; float margeGauche = (vueGrille.getWidth() - tailleCase * NB_COLONNES) / 2f;
float margeHaut = (vueGrille.getHeight() - tailleCase * NB_LIGNES) / 2f; float margeHaut = (vueGrille.getHeight() - tailleCase * NB_LIGNES) / 2f;
// Conversion des coordonnées pixels en indices de tableau (0 à 5)
ligneTouchee = (int) ((touchDebutY - margeHaut) / tailleCase); ligneTouchee = (int) ((touchDebutY - margeHaut) / tailleCase);
colonneTouchee = (int) ((touchDebutX - margeGauche) / tailleCase); colonneTouchee = (int) ((touchDebutX - margeGauche) / tailleCase);
// Sécurité pour éviter de sortir des limites du tableau si on touche les bords
ligneTouchee = Math.max(0, Math.min(NB_LIGNES - 1, ligneTouchee)); ligneTouchee = Math.max(0, Math.min(NB_LIGNES - 1, ligneTouchee));
colonneTouchee = Math.max(0, Math.min(NB_COLONNES - 1, colonneTouchee)); colonneTouchee = Math.max(0, Math.min(NB_COLONNES - 1, colonneTouchee));
} }
@@ -75,8 +85,10 @@ public class GestionnaireTactile implements View.OnTouchListener {
float dx = event.getX() - touchDebutX; float dx = event.getX() - touchDebutX;
float dy = event.getY() - touchDebutY; float dy = event.getY() - touchDebutY;
// on détermine si le joueur glisse vers le côté ou vers le haut/bas
if (estLigne == null) { if (estLigne == null) {
if (Math.abs(dx) > SEUIL_DIRECTION_PX || Math.abs(dy) > SEUIL_DIRECTION_PX) { if (Math.abs(dx) > SEUIL_DIRECTION_PX || Math.abs(dy) > SEUIL_DIRECTION_PX) {
// On verrouille l'axe : celui qui a la plus grande distance parcourue gagne
estLigne = Math.abs(dx) >= Math.abs(dy); estLigne = Math.abs(dx) >= Math.abs(dy);
if (estLigne) { if (estLigne) {
@@ -13,8 +13,6 @@ public class MainActivity extends Activity {
private Button btnMenu; private Button btnMenu;
private VueGrille vueGrille; private VueGrille vueGrille;
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
@@ -24,7 +22,6 @@ public class MainActivity extends Activity {
long graine = getIntent().getLongExtra("graine", System.currentTimeMillis()); long graine = getIntent().getLongExtra("graine", System.currentTimeMillis());
hardMode = getSharedPreferences("chuzzle_prefs", MODE_PRIVATE).getBoolean("hard_mode", false); hardMode = getSharedPreferences("chuzzle_prefs", MODE_PRIVATE).getBoolean("hard_mode", false);
etatJeu = new EtatJeu(graine, hardMode); etatJeu = new EtatJeu(graine, hardMode);
// --- Restauration si retour de pause // --- Restauration si retour de pause
@@ -21,6 +21,10 @@ public class Plateau {
initialiserGrilleSansTriples(); initialiserGrilleSansTriples();
} }
/**
* Remplit la grille aléatoirement au début de la partie.
* On s'assure qu'aucune série de 3 n'est créée automatiquement au démarrage.
*/
private void initialiserGrilleSansTriples() { private void initialiserGrilleSansTriples() {
for (int l = 0; l < NB_LIGNES; l++) { for (int l = 0; l < NB_LIGNES; l++) {
for (int c = 0; c < NB_COLONNES; c++) { for (int c = 0; c < NB_COLONNES; c++) {
@@ -33,6 +37,9 @@ public class Plateau {
} }
} }
/**
* Vérifie si placer une couleur à une position précise créerait un alignement de 3.
*/
private boolean creeTriple(int l, int c, int val) { private boolean creeTriple(int l, int c, int val) {
if (c >= 2 && grille[l][c - 1] == val && grille[l][c - 2] == val) { if (c >= 2 && grille[l][c - 1] == val && grille[l][c - 2] == val) {
return true; return true;
@@ -43,6 +50,10 @@ public class Plateau {
return false; return false;
} }
/**
* Fait défiler une colonne horizontalement. C'est un mouvement circulaire :
* les cases qui sortent par la gauche reviennent par la droite (comme un rouleau)
*/
public void decalerLigne(int ligne, int sens) { public void decalerLigne(int ligne, int sens) {
int s = ((sens % NB_COLONNES) + NB_COLONNES) % NB_COLONNES; int s = ((sens % NB_COLONNES) + NB_COLONNES) % NB_COLONNES;
for (int etape = 0; etape < s; etape++) { for (int etape = 0; etape < s; etape++) {
@@ -54,6 +65,10 @@ public class Plateau {
} }
} }
/**
* Fait défiler une colonne verticalement. C'est un mouvement circulaire :
* les cases qui sortent par le bas reviennent par le haut.
*/
public void decalerColonne(int col, int sens) { public void decalerColonne(int col, int sens) {
int s = ((sens % NB_LIGNES) + NB_LIGNES) % NB_LIGNES; int s = ((sens % NB_LIGNES) + NB_LIGNES) % NB_LIGNES;
for (int etape = 0; etape < s; etape++) { for (int etape = 0; etape < s; etape++) {
@@ -65,6 +80,10 @@ public class Plateau {
} }
} }
/**
* Parcourt toute la grille pour identifier les alignements de 3 couleurs ou plus.
* Retourne nne liste de coordonnées [ligne, colonne] des cases à supprimer.
*/
public List<int[]> trouverSeries() { public List<int[]> trouverSeries() {
boolean[][] aSupprimer = new boolean[NB_LIGNES][NB_COLONNES]; boolean[][] aSupprimer = new boolean[NB_LIGNES][NB_COLONNES];
// Analyse horizontale // Analyse horizontale
@@ -112,6 +131,10 @@ public class Plateau {
return positions; return positions;
} }
/**
* Vérifie si une ligne ou une colonne contient au moins une case verrouillée.
* Si c'est le cas, elle ne peut pas être déplacée par le joueur.
*/
public boolean estBloque(boolean estLigne, int index) { public boolean estBloque(boolean estLigne, int index) {
if (estLigne) { if (estLigne) {
for (int c = 0; c < NB_COLONNES; c++) { for (int c = 0; c < NB_COLONNES; c++) {
@@ -129,6 +152,10 @@ public class Plateau {
return false; return false;
} }
/**
* Ajoute un nouveau verrou sur une case libre au hasard.
* La fréquence d'apparition augmente au fur et à mesure que la partie avance.
*/
public void ajouterVerrou(int nbCoups) { public void ajouterVerrou(int nbCoups) {
int intervalle = Math.max(1, 5 - nbCoups / 10); int intervalle = Math.max(1, 5 - nbCoups / 10);
if (nbCoups % intervalle != 0) { if (nbCoups % intervalle != 0) {
@@ -149,6 +176,9 @@ public class Plateau {
verrous[choix[0]][choix[1]] = true; verrous[choix[0]][choix[1]] = true;
} }
/**
* Libère les verrous sur les cases qui viennent d'être complétées dans une série.
*/
public void libererVerrous(boolean[][] masque) { public void libererVerrous(boolean[][] masque) {
for (int l = 0; l < NB_LIGNES; l++) { for (int l = 0; l < NB_LIGNES; l++) {
for (int c = 0; c < NB_COLONNES; c++) { for (int c = 0; c < NB_COLONNES; c++) {
@@ -159,6 +189,9 @@ public class Plateau {
} }
} }
/**
* Création d'un double de la grille actuelle (utile pour tester des mouvements).
*/
public int[][] copierGrille() { public int[][] copierGrille() {
int[][] copie = new int[NB_LIGNES][NB_COLONNES]; int[][] copie = new int[NB_LIGNES][NB_COLONNES];
for (int l = 0; l < NB_LIGNES; l++) { for (int l = 0; l < NB_LIGNES; l++) {
@@ -181,6 +214,10 @@ public class Plateau {
return verrous; return verrous;
} }
/**
* Logique de gravité : les cases vides (supprimées) sont comblées par les cases du dessus.
* De nouvelles couleurs sont générées au sommet du plateau.
*/
public void faireTomber(boolean[][] aSupprimer) { public void faireTomber(boolean[][] aSupprimer) {
for (int col = 0; col < NB_COLONNES; col++) { for (int col = 0; col < NB_COLONNES; col++) {
List<Integer> survivants = new ArrayList<>(); List<Integer> survivants = new ArrayList<>();
@@ -8,11 +8,10 @@ import android.widget.Button;
import android.widget.EditText; import android.widget.EditText;
import android.widget.Toast; import android.widget.Toast;
public class SeedActivity extends Activity implements View.OnClickListener { public class SeedActivity extends Activity {
private EditText etGraine; private EditText etGraine;
private Button btnJouer; private Button btnJouer;
private Button btnRetour; private Button btnRetour;
@Override @Override
@@ -23,43 +22,18 @@ public class SeedActivity extends Activity implements View.OnClickListener {
etGraine = findViewById(R.id.etGraine); etGraine = findViewById(R.id.etGraine);
btnJouer = findViewById(R.id.btnJouer); btnJouer = findViewById(R.id.btnJouer);
btnRetour = findViewById(R.id.btnBack); btnRetour = findViewById(R.id.btnBack);
SeedControleur controleur = new SeedControleur(this, etGraine);
btnRetour.setOnClickListener(this); btnRetour.setOnClickListener(controleur);
btnJouer.setOnClickListener(controleur);
btnJouer.setOnClickListener(this);
}
@Override
public void onClick(View v) {
if (v == btnJouer) {
lancerPartieAvecGraine();
}
if (v == btnRetour) {
Intent intent = new Intent(this, MenuActivity.class);
startActivity(intent);
}
}
private void lancerPartieAvecGraine() {
String texte = etGraine.getText().toString().trim();
if (texte.isEmpty()) {
Toast.makeText(this, "Veuillez entrer une graine.",
Toast.LENGTH_SHORT
).show();
return;
}
long graine;
try {
graine = Long.parseLong(texte);
} catch (NumberFormatException e) {
graine = texte.hashCode();
} }
public void lancerPartie(long graine) {
Intent intent = new Intent(this, MainActivity.class); Intent intent = new Intent(this, MainActivity.class);
intent.putExtra("graine", graine); intent.putExtra("graine", graine);
startActivity(intent); startActivity(intent);
} }
public void retourMenu() {
Intent intent = new Intent(this, MenuActivity.class);
startActivity(intent);
}
} }
@@ -0,0 +1,53 @@
package sae.chuzzle;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;
/**
* Contrôleur pour la saisie de la graine.
* Gère la validation de la saisie et la navigation.
*/
public class SeedControleur implements View.OnClickListener {
private final SeedActivity activite;
private final EditText etGraine;
public SeedControleur(SeedActivity activite, EditText etGraine) {
this.activite = activite;
this.etGraine = etGraine;
}
@Override
public void onClick(View v) {
int id = v.getId();
if (id == R.id.btnJouer) {
traiterGraine();
} else if (id == R.id.btnBack) {
activite.retourMenu();
}
}
/**
* Valide le texte saisi et demande à l'activité de lancer la partie.
*/
private void traiterGraine() {
String texte = etGraine.getText().toString().trim();
if (texte.isEmpty()) {
Toast.makeText(activite, "Veuillez entrer une graine.", Toast.LENGTH_SHORT).show();
return;
}
long graine;
try {
graine = Long.parseLong(texte);
} catch (NumberFormatException e) {
graine = texte.hashCode();
}
activite.lancerPartie(graine);
}
}
+7 -2
View File
@@ -19,7 +19,7 @@ public class VueGrille extends View {
private static final int NB_COLONNES = 6; private static final int NB_COLONNES = 6;
private static final int NB_TYPES = 7; private static final int NB_TYPES = 7;
/** Symboles pour le mode daltonien, un par type. */ /** Symboles pour les daltoniens, un par type. */
private static final String[] SYMBOLES = {"", "", "", "", "", "", ""}; private static final String[] SYMBOLES = {"", "", "", "", "", "", ""};
// Données nécessaires au dessin // Données nécessaires au dessin
@@ -130,14 +130,18 @@ public class VueGrille extends View {
pinceauSymbole.setTextSize(tailleCase * 0.4f); pinceauSymbole.setTextSize(tailleCase * 0.4f);
// On parcourt chaque case de la grille pour la dessiner
for (int ligne = 0; ligne < NB_LIGNES; ligne++) { for (int ligne = 0; ligne < NB_LIGNES; ligne++) {
for (int colonne = 0; colonne < NB_COLONNES; colonne++) { for (int colonne = 0; colonne < NB_COLONNES; colonne++) {
float offsetX = 0f; float offsetX = 0f;
float offsetY = 0f; float offsetY = 0f;
// Si un glissement est en cours, on calcule le décalage visuel
if (animEstLigne != null) { if (animEstLigne != null) {
// On convertit les pixels du doigt en nombre de cases de décalage
int nbCases = Math.round(animDecalagePx / tailleCase); int nbCases = Math.round(animDecalagePx / tailleCase);
// On applique le décalage uniquement à la ligne ou colonne que le joueur bouge
if (animEstLigne && ligne == animIndex) { if (animEstLigne && ligne == animIndex) {
offsetX = nbCases * tailleCase; offsetX = nbCases * tailleCase;
} else if (!animEstLigne && colonne == animIndex) { } else if (!animEstLigne && colonne == animIndex) {
@@ -150,6 +154,7 @@ public class VueGrille extends View {
float x2 = margeGauche + (colonne + 1) * tailleCase - 6 + offsetX; float x2 = margeGauche + (colonne + 1) * tailleCase - 6 + offsetX;
float y2 = margeHaut + (ligne + 1) * tailleCase - 6 + offsetY; float y2 = margeHaut + (ligne + 1) * tailleCase - 6 + offsetY;
// On dessine la case (et ses éventuelles copies pour l'effet de boucle)
dessinerCase(canvas, ligne, colonne, x1, y1, x2, y2, dessinerCase(canvas, ligne, colonne, x1, y1, x2, y2,
tailleCase, margeGauche, margeHaut, offsetX, offsetY); tailleCase, margeGauche, margeHaut, offsetX, offsetY);
} }
@@ -170,7 +175,7 @@ public class VueGrille extends View {
// Dessin case principale // Dessin case principale
dessinerRectCase(canvas, ligne, colonne, x1, y1, x2, y2); dessinerRectCase(canvas, ligne, colonne, x1, y1, x2, y2);
// Réapparition de l'autre côté (wrap) // Réapparition de l'autre côté (effet boucle infini)
if (offsetX != 0f) { if (offsetX != 0f) {
float bordD = margeGauche + largeurGrille; float bordD = margeGauche + largeurGrille;
float bordG = margeGauche; float bordG = margeGauche;