Feat: Implémenter la boîte de dialogue de fin de partie multijoueur stylisée

Remplace le comportement précédent à la fin d'une partie multijoueur par une boîte de dialogue claire et stylisée.

- Ajout d'une AlertDialog dans MultiplayerActivity affichée via showEndGameDialog lorsque la partie se termine (déclenché par handleMultiplayerGameOver).
- La boîte de dialogue indique si le joueur a gagné, perdu ou fait match nul.
- Inclut un bouton unique ('Menu principal') pour revenir à MainActivity, fermer l'activité multijoueur et clore la connexion WebSocket.
- Création d'un layout personnalisé (dialog_multiplayer_game_over.xml) pour cette boîte de dialogue afin qu'elle corresponde au style visuel des dialogues existants en mode solo (par exemple, dialog_game_over.xml).
- Mise à jour de showEndGameDialog pour charger et utiliser ce layout personnalisé au lieu des méthodes standard d'AlertDialog.Builder pour le titre/message/bouton.
- Ajout des ressources string nécessaires pour les titres, messages et textes des boutons de la nouvelle boîte de dialogue.
This commit is contained in:
Augustin ROUX 2025-04-06 16:20:43 +02:00
parent 1842213cac
commit 2b5dc6b85f
4 changed files with 119 additions and 35 deletions

View File

@ -7,12 +7,15 @@ import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
@ -577,40 +580,13 @@ public class MultiplayerActivity extends AppCompatActivity {
}
// Met à jour l'UI sur le thread principal
runOnUiThread(() -> {
showGameOverMessage(finalState); // Affiche le message de fin
showEndGameDialog(finalState);
disableSwipe(); // Désactive les swipes
closeWebSocket(); // Ferme la connexion
});
}
}
/**
* Affiche le message approprié dans le TextView de statut en fonction du résultat de la partie.
* Gère les cas de victoire, défaite, match nul, et victoire par forfait (heuristique).
*
* @param finalState L'état final du jeu {@link GameStateResponse}.
*/
private void showGameOverMessage(GameStateResponse finalState) {
String endMessage;
boolean wonByForfeit = false;
// Heuristique pour détecter une victoire par forfait (si on gagne sans atteindre l'objectif)
// Cela nécessite que le serveur attribue correctement le gagnant en cas de déconnexion adverse.
if (myPlayerId != null && myPlayerId.equals(finalState.getWinnerId()) && finalState.getMyScore(myPlayerId) < finalState.getTargetScore()) {
wonByForfeit = true;
}
// Choisit le message en fonction du résultat
if ("DRAW".equals(finalState.getWinnerId())) { endMessage = getString(R.string.game_over_draw); }
else if (wonByForfeit) { endMessage = "Opponent disconnected - You Win!"; }
else if (myPlayerId != null && myPlayerId.equals(finalState.getWinnerId())) { endMessage = getString(R.string.game_over_won); }
else if (opponentPlayerId != null && opponentPlayerId.equals(finalState.getWinnerId())) { endMessage = getString(R.string.game_over_lost); }
else { endMessage = getString(R.string.game_over_generic); } // Cas générique
// Affiche le message et efface l'indicateur de tour
statusTextMulti.setText(endMessage);
turnIndicatorMulti.setText("");
}
/**
* Synchronise la vue du plateau de jeu ({@link #boardGridLayoutMulti}) avec l'état
* du plateau fourni.
@ -968,6 +944,69 @@ public class MultiplayerActivity extends AppCompatActivity {
statusTextMulti.setText(myTurn ? "" : getString(R.string.multiplayer_status_waiting_opponent));
}
/**
* Affiche une boîte de dialogue indiquant la fin de la partie multijoueur (Victoire, Défaite, Égalité)
* en utilisant un layout personnalisé pour correspondre au style des dialogues solo.
* Propose un bouton pour revenir à l'écran principal (MainActivity).
*
* @param finalState L'état final du jeu reçu du serveur.
*/
private void showEndGameDialog(GameStateResponse finalState) {
if (isFinishing() || finalState == null || myPlayerId == null) {
return;
}
// Détermine le résultat
boolean isWin = myPlayerId.equals(finalState.getWinnerId());
boolean isDraw = "DRAW".equals(finalState.getWinnerId());
String titleText;
String messageText;
if (isWin) {
titleText = getString(R.string.game_over_won);
messageText = getString(R.string.multiplayer_win_message);
} else if (isDraw) {
titleText = getString(R.string.game_over_draw);
messageText = getString(R.string.multiplayer_draw_message);
} else {
titleText = getString(R.string.game_over_lost);
messageText = getString(R.string.multiplayer_loss_message);
}
// Création du Builder et inflation du layout personnalisé
AlertDialog.Builder builder = new AlertDialog.Builder(this);
LayoutInflater inflater = getLayoutInflater();
View dialogView = inflater.inflate(R.layout.dialog_multiplayer_game_over, null); // Utilise le nouveau layout
builder.setView(dialogView);
builder.setCancelable(false);
// Récupération des vues DANS le layout personnalisé
TextView titleTextView = dialogView.findViewById(R.id.dialogTitleMultiGameOver);
TextView messageTextView = dialogView.findViewById(R.id.dialogMessageMultiGameOver);
Button mainMenuButton = dialogView.findViewById(R.id.dialogButtonMainMenu);
// Définition du contenu des vues
titleTextView.setText(titleText);
messageTextView.setText(messageText);
// Création de la boîte de dialogue AVANT de définir l'OnClickListener du bouton
final AlertDialog dialog = builder.create();
// Configuration du bouton DANS le layout personnalisé
mainMenuButton.setOnClickListener(v -> {
// Action lorsque l'utilisateur clique sur le bouton "Menu principal"
dialog.dismiss();
closeWebSocket();
Intent intent = new Intent(MultiplayerActivity.this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(intent);
finish();
});
dialog.show(); // Affiche la boîte de dialogue
}
/**
* Énumération privée représentant les quatre directions de mouvement possibles.
*/

View File

@ -12,17 +12,20 @@
android:id="@+id/multiplayerInfoPanel"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="36dp"
android:orientation="horizontal"
android:padding="@dimen/padding_general"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent">
app:layout_constraintTop_toTopOf="parent">
<TextView
android:id="@+id/myScoreLabelMulti"
style="@style/ScoreLabelStyle"
android:layout_weight="1"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/margin_between_elements"
android:layout_weight="1"
android:text="Mon Score:\n0" />
<TextView
@ -30,17 +33,19 @@
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center"
android:paddingStart="8dp" android:paddingEnd="8dp"
android:paddingStart="8dp"
android:paddingEnd="8dp"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="@color/text_tile_low"
android:textStyle="bold"
android:textAppearance="?android:attr/textAppearanceMedium"
tools:text="À votre tour"/>
tools:text="À votre tour" />
<TextView
android:id="@+id/opponentScoreLabelMulti"
style="@style/ScoreLabelStyle"
android:layout_weight="1"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/margin_between_elements"
android:layout_weight="1"
android:text="Adversaire:\n0" />
</LinearLayout>

View File

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="24dp"
android:background="@drawable/dialog_background">
<TextView
android:id="@+id/dialogTitleMultiGameOver"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/game_over_title" android:textSize="20sp"
android:textStyle="bold"
android:textColor="@color/text_tile_low"
android:gravity="center"
android:layout_marginBottom="8dp"/>
<TextView
android:id="@+id/dialogMessageMultiGameOver"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/multiplayer_win_message" android:textSize="16sp"
android:textColor="@color/text_tile_low"
android:gravity="center"
android:layout_marginBottom="16dp"/>
<Button
android:id="@+id/dialogButtonMainMenu"
style="@style/ButtonStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1" android:layout_marginStart="0dp" android:layout_marginEnd="0dp" android:text="@string/return_to_main_menu" />
</LinearLayout>

View File

@ -122,4 +122,9 @@
<string name="game_over_won">You Won!</string>
<string name="game_over_lost">You Lost.</string>
<string name="game_over_generic">Game Over!</string>
<string name="return_to_main_menu">Main menu</string>
<string name="multiplayer_win_message">Congratulations! You won the game.</string>
<string name="multiplayer_loss_message">Too bad! Your opponent was better this time.</string>
<string name="multiplayer_draw_message">It\'s a draw! A hard-fought game.</string>
</resources>