feat: Ajout du hub de jeux et nouveau mode 89++

Nouvelles fonctionnalités:
- Hub de sélection de jeux avec cartes animées
- Refonte complète de Boidelo Classic avec nouvelle architecture
- Nouveau mode 89++ : assistant de jeu avec timer et défis
- Système de joueurs dynamique avec ajout/suppression
- Interface moderne et cohérente entre les jeux

Améliorations:
- Système de défis avec pause pendant l'affichage
- Gestion des gorgées avec slider (1-8)
- Statistiques de joueurs en temps réel
- Bouton retour fonctionnel avec gestion de la notch

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
feldenr
2026-01-14 22:50:55 +01:00
parent ecb44f1934
commit 1b3d67526d
30 changed files with 3710 additions and 87 deletions
@@ -0,0 +1,121 @@
package com.example.boidelov3.hub;
import android.content.Intent;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.example.boidelov3.R;
import com.example.boidelov3.games.boideloclassic.BoideloClassicSetupActivity;
import com.example.boidelov3.hub.adapter.GameAdapter;
import com.example.boidelov3.hub.model.GameInfo;
import java.util.ArrayList;
import java.util.List;
/**
* GameSelectionActivity - Hub principal de sélection des jeux
* Cette activité remplace l'ancienne MainActivity et sert de point d'entrée
* pour tous les jeux disponibles dans Boidelo.
*/
public class GameSelectionActivity extends AppCompatActivity implements GameAdapter.OnItemClickListener {
private RecyclerView gamesRecyclerView;
private GameAdapter gameAdapter;
private List<GameInfo> gamesList;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_game_selection);
initViews();
setupGamesList();
setupRecyclerView();
}
/**
* Initialise les vues de l'activité
*/
private void initViews() {
gamesRecyclerView = findViewById(R.id.gamesRecyclerView);
gamesRecyclerView.setLayoutManager(new LinearLayoutManager(this));
}
/**
* Configure la liste des jeux disponibles
*/
private void setupGamesList() {
gamesList = new ArrayList<>();
// Boidelo Classic - Le jeu original
gamesList.add(new GameInfo(
"Boidelo Classic",
"Le jeu original de questions et défis",
R.drawable.ic_boidelo_classic,
GameInfo.GameType.BOIDELO_CLASSIC,
true
));
// 89++ - Jeu de cartes
gamesList.add(new GameInfo(
"89++",
"Jeu de cartes avec timer et défis",
R.drawable.ic_game_89,
GameInfo.GameType.GAME_89,
true // Available now
));
// Undercover - Jeu de déduction
gamesList.add(new GameInfo(
"Undercover",
"Trouvez l'undercover avant qu'il ne soit trop tard!",
R.drawable.ic_undercover,
GameInfo.GameType.UNDERCOVER,
false // Coming soon
));
// Jeux de règles
gamesList.add(new GameInfo(
"Règles de jeux",
"Découvrez les règles des jeux d'ambiance populaires",
R.drawable.ic_rules,
GameInfo.GameType.RULES,
false // Coming soon
));
}
/**
* Configure le RecyclerView avec l'adaptateur
*/
private void setupRecyclerView() {
gameAdapter = new GameAdapter(gamesList, this);
gamesRecyclerView.setAdapter(gameAdapter);
}
/**
* Gère le clic sur un jeu de la liste
* @param gameInfo Le jeu sélectionné
*/
@Override
public void onItemClick(GameInfo gameInfo) {
if (!gameInfo.isAvailable()) {
// Afficher un message "Coming soon"
return;
}
switch (gameInfo.getGameType()) {
case BOIDELO_CLASSIC:
startActivity(new Intent(this, BoideloClassicSetupActivity.class));
break;
case GAME_89:
startActivity(new Intent(this, com.example.boidelov3.games.game89.Game89SetupActivity.class));
break;
case UNDERCOVER:
// TODO: Implémenter UndercoverSetupActivity
break;
case RULES:
// TODO: Implémenter RulesListActivity
break;
}
}
}
@@ -0,0 +1,81 @@
package com.example.boidelov3.hub.adapter;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.example.boidelov3.R;
import com.example.boidelov3.hub.model.GameInfo;
import java.util.List;
/**
* GameAdapter - Adaptateur pour afficher la liste des jeux dans le RecyclerView
*/
public class GameAdapter extends RecyclerView.Adapter<GameAdapter.GameViewHolder> {
private List<GameInfo> gamesList;
private OnItemClickListener listener;
public interface OnItemClickListener {
void onItemClick(GameInfo gameInfo);
}
public GameAdapter(List<GameInfo> gamesList, OnItemClickListener listener) {
this.gamesList = gamesList;
this.listener = listener;
}
@NonNull
@Override
public GameViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_game_card, parent, false);
return new GameViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull GameViewHolder holder, int position) {
GameInfo gameInfo = gamesList.get(position);
holder.bind(gameInfo, listener);
}
@Override
public int getItemCount() {
return gamesList.size();
}
static class GameViewHolder extends RecyclerView.ViewHolder {
private ImageView gameIcon;
private TextView gameName;
private TextView gameDescription;
private View statusText;
public GameViewHolder(@NonNull View itemView) {
super(itemView);
gameIcon = itemView.findViewById(R.id.gameIcon);
gameName = itemView.findViewById(R.id.gameName);
gameDescription = itemView.findViewById(R.id.gameDescription);
statusText = itemView.findViewById(R.id.statusText);
}
public void bind(GameInfo gameInfo, OnItemClickListener listener) {
gameName.setText(gameInfo.getName());
gameDescription.setText(gameInfo.getDescription());
gameIcon.setImageResource(gameInfo.getIconResId());
if (gameInfo.isAvailable()) {
statusText.setVisibility(View.GONE);
itemView.setEnabled(true);
itemView.setAlpha(1.0f);
itemView.setOnClickListener(v -> listener.onItemClick(gameInfo));
} else {
statusText.setVisibility(View.VISIBLE);
itemView.setEnabled(false);
itemView.setAlpha(0.6f);
}
}
}
}
@@ -0,0 +1,39 @@
package com.example.boidelov3.hub.model;
/**
* GameInfo - Modèle représentant un jeu dans le hub
* Contient les informations de base pour afficher et lancer un jeu
*/
public class GameInfo {
private String name;
private String description;
private int iconResId;
private GameType gameType;
private boolean available;
public enum GameType {
BOIDELO_CLASSIC,
GAME_89,
UNDERCOVER,
RULES
}
public GameInfo(String name, String description, int iconResId, GameType gameType, boolean available) {
this.name = name;
this.description = description;
this.iconResId = iconResId;
this.gameType = gameType;
this.available = available;
}
// Getters
public String getName() { return name; }
public String getDescription() { return description; }
public int getIconResId() { return iconResId; }
public GameType getGameType() { return gameType; }
public boolean isAvailable() { return available; }
// Setters
public void setAvailable(boolean available) { this.available = available; }
}