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.animation.ObjectAnimator;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.os.Looper; import android.os.Looper;
import android.util.TypedValue; import android.util.TypedValue;
import android.view.Gravity; import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar; import android.widget.ProgressBar;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
@ -577,40 +580,13 @@ public class MultiplayerActivity extends AppCompatActivity {
} }
// Met à jour l'UI sur le thread principal // Met à jour l'UI sur le thread principal
runOnUiThread(() -> { runOnUiThread(() -> {
showGameOverMessage(finalState); // Affiche le message de fin showEndGameDialog(finalState);
disableSwipe(); // Désactive les swipes disableSwipe(); // Désactive les swipes
closeWebSocket(); // Ferme la connexion 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 * Synchronise la vue du plateau de jeu ({@link #boardGridLayoutMulti}) avec l'état
* du plateau fourni. * du plateau fourni.
@ -968,6 +944,69 @@ public class MultiplayerActivity extends AppCompatActivity {
statusTextMulti.setText(myTurn ? "" : getString(R.string.multiplayer_status_waiting_opponent)); 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. * Énumération privée représentant les quatre directions de mouvement possibles.
*/ */

View File

@ -12,17 +12,20 @@
android:id="@+id/multiplayerInfoPanel" android:id="@+id/multiplayerInfoPanel"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="36dp"
android:orientation="horizontal" android:orientation="horizontal"
android:padding="@dimen/padding_general" 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_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"> app:layout_constraintTop_toTopOf="parent">
<TextView <TextView
android:id="@+id/myScoreLabelMulti" android:id="@+id/myScoreLabelMulti"
style="@style/ScoreLabelStyle" style="@style/ScoreLabelStyle"
android:layout_weight="1" android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/margin_between_elements" android:layout_marginEnd="@dimen/margin_between_elements"
android:layout_weight="1"
android:text="Mon Score:\n0" /> android:text="Mon Score:\n0" />
<TextView <TextView
@ -30,17 +33,19 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="match_parent" android:layout_height="match_parent"
android:gravity="center" 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:textColor="@color/text_tile_low"
android:textStyle="bold" android:textStyle="bold"
android:textAppearance="?android:attr/textAppearanceMedium" tools:text="À votre tour" />
tools:text="À votre tour"/>
<TextView <TextView
android:id="@+id/opponentScoreLabelMulti" android:id="@+id/opponentScoreLabelMulti"
style="@style/ScoreLabelStyle" style="@style/ScoreLabelStyle"
android:layout_weight="1" android:layout_height="wrap_content"
android:layout_marginStart="@dimen/margin_between_elements" android:layout_marginStart="@dimen/margin_between_elements"
android:layout_weight="1"
android:text="Adversaire:\n0" /> android:text="Adversaire:\n0" />
</LinearLayout> </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_won">You Won!</string>
<string name="game_over_lost">You Lost.</string> <string name="game_over_lost">You Lost.</string>
<string name="game_over_generic">Game Over!</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> </resources>