From 0939e7369de1f2134cc5b6b59ee0bacfca51962a Mon Sep 17 00:00:00 2001 From: lecointre Date: Sun, 30 Nov 2025 15:40:46 +0100 Subject: [PATCH] Menu v2 --- src/main.c | 67 ++++++++++++++ src/menu_view.c | 225 ++++++++++++++++++++++++++++++++++++++++++++++++ src/menu_view.h | 24 ++++++ 3 files changed, 316 insertions(+) diff --git a/src/main.c b/src/main.c index e69de29..6341921 100644 --- a/src/main.c +++ b/src/main.c @@ -0,0 +1,67 @@ +/* src/main.c + * Point d'entrée du programme Taquin. + * Gère la boucle principale des événements et la transition de vue (Menu -> Jeu). + */ + +#include "menu_view.h" +#include /* La bibliothèque IUT */ +#include /* Pour EXIT_SUCCESS */ +#include /* Pour printf */ + +/* Constantes de la fenêtre (doivent être disponibles partout) */ +#define WINDOW_WIDTH 800 +#define WINDOW_HEIGHT 600 + +/* Temps de rafraîchissement (pour économiser le CPU) */ +#define REFRESH_CYCLE 50000L /* 50 ms */ + +int main(void) +{ + menu_state_t menu_state; + unsigned long next_update; + + /* 1. Initialisation de l'environnement IUT */ + InitialiserGraphique(); + CreerFenetre(10, 10, WINDOW_WIDTH, WINDOW_HEIGHT); + + menu_init(&menu_state); + + next_update = Microsecondes() + REFRESH_CYCLE; + + /* 2. Boucle du Menu (tant que le joueur n'a pas validé ou quitté) */ + while (menu_state.ready_to_play == 0) + { + /* Gestion du temps et Rendu (dessin) */ + if (Microsecondes() > next_update) + { + menu_render(&menu_state); + + /* FORCER L'AFFICHAGE : Copier l'écran 0 vers l'écran 0 + (Technique souvent nécessaire avec XLib pour forcer le rafraîchissement) */ + CopierZone(0, 0, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, 0, 0); + + next_update = Microsecondes() + REFRESH_CYCLE; + } + + /* Gestion des événements Souris */ + if (SourisCliquee()) + { + /* _X et _Y sont mis à jour par SourisCliquee() */ + menu_handle_mouse_click(&menu_state); + } + + /* Gestion des événements Clavier */ + menu_handle_key(&menu_state); + } + + /* 3. Sortie */ + if (menu_state.ready_to_play == 1) { + printf("Configuration valide. Image %d choisie, grille %d x %d. Lancement du jeu...\n", + menu_state.selected_image + 1, menu_state.rows, menu_state.cols); + + /* TODO: Appeler game_init, game_shuffle et la boucle de jeu (GRANDE PARTIE 2) */ + } + + FermerGraphique(); + return EXIT_SUCCESS; +} diff --git a/src/menu_view.c b/src/menu_view.c index e69de29..cdb6d1b 100644 --- a/src/menu_view.c +++ b/src/menu_view.c @@ -0,0 +1,225 @@ +/* src/menu_view.c + * Implémentation complète de l'interface de configuration (Menu) + * Utilise la bibliothèque graphique IUT (graph.h). + */ + +#include "menu_view.h" +#include +#include /* Pour sprintf */ +#include /* Pour les calculs simples */ + +/* --- DÉCLARATIONS (CONSTANTES ET VARIABLES GLOBALES IUT) --- */ + +/* Constantes de positionnement */ +#define IMG_PREVIEW_SIZE 150 +#define IMG_START_X 50 +#define IMG_START_Y 150 +#define IMG_SPACING 200 +#define BUTTON_SIZE 30 +#define DIM_START_Y 350 + +/* Variables globales de la bibliothèque IUT pour la souris */ +extern int _X; +extern int _Y; + +/* --- PROTOTYPES DES UTILITAIRES PRIVÉS (OBLIGATOIRE EN C89) --- */ + +static int is_in_rect(int x_click, int y_click, int rx, int ry, int rw, int rh); +static void draw_button(int x, int y, const char *text, couleur C_BG); +static void draw_text_centered(int x, int y, int w, int h, const char *text, int size); + +/* --- IMPLÉMENTATION DES FONCTIONS PUBLIQUES (.h) --- */ + +/* Initialise l'état du menu */ +void menu_init(menu_state_t *state) +{ + state->selected_image = 0; /* Image 1 sélectionnée par défaut */ + state->rows = MIN_DIMENSION; + state->cols = MIN_DIMENSION; + state->ready_to_play = 0; +} + +/* Dessine l'écran de configuration du menu */ +void menu_render(const menu_state_t *state) +{ + int i; + couleur C_FOND = CouleurParNom("white"); + couleur C_SELECTION = CouleurParNom("red"); + couleur C_TEXTE = CouleurParNom("black"); + couleur C_BOUTON = CouleurParNom("dark gray"); + couleur C_START = CouleurParNom("green"); + char buffer[50]; + + EffacerEcran(C_FOND); + ChoisirCouleurDessin(C_TEXTE); + + /* 1. Titre et Section Image */ + EcrireTexte(IMG_START_X, 50, "CONFIGURATION DU JEU TAQUIN", 2); + EcrireTexte(IMG_START_X, 100, "1. Choisir l'image :", 1); + + /* BOUCLE : Affichage des 3 aperçus d'images */ + for (i = 0; i < NUM_IMAGES; i++) { + int x = IMG_START_X + i * IMG_SPACING; + int y = IMG_START_Y; + char path[30]; + + sprintf(path, "assets/image%d.png", i + 1); + + /* Affiche l'image */ + ChargerImage(path, x, y, 0, 0, IMG_PREVIEW_SIZE, IMG_PREVIEW_SIZE); + + /* Encadrement si sélectionné */ + if (state->selected_image == i) { + ChoisirCouleurDessin(C_SELECTION); + DessinerRectangle(x - 5, y - 5, IMG_PREVIEW_SIZE + 10, IMG_PREVIEW_SIZE + 10); + } + } + ChoisirCouleurDessin(C_TEXTE); + + /* 2. Section Dimensions */ + int dim_section_x = IMG_START_X; + int button_l_offset = 180; + int button_c_offset = 400; + + EcrireTexte(dim_section_x, DIM_START_Y, "2. Choisir les dimensions (3x3 a 8x8) :", 1); + + /* Affichage de la taille LIGNES */ + EcrireTexte(dim_section_x, DIM_START_Y + 40, "Lignes :", 0); + sprintf(buffer, "%d", state->rows); + EcrireTexte(dim_section_x + 100, DIM_START_Y + 40, buffer, 0); + + /* Affichage de la taille COLONNES */ + EcrireTexte(dim_section_x + 250, DIM_START_Y + 40, "Colonnes :", 0); + sprintf(buffer, "%d", state->cols); + EcrireTexte(dim_section_x + 350, DIM_START_Y + 40, buffer, 0); + + /* Boutons de contrôle LIGNES */ + draw_button(dim_section_x + button_l_offset, DIM_START_Y + 30, "+", C_BOUTON); + draw_button(dim_section_x + button_l_offset + 40, DIM_START_Y + 30, "-", C_BOUTON); + + /* Boutons de contrôle COLONNES */ + draw_button(dim_section_x + button_c_offset, DIM_START_Y + 30, "+", C_BOUTON); + draw_button(dim_section_x + button_c_offset + 40, DIM_START_Y + 30, "-", C_BOUTON); + + + /* 3. Bouton DÉMARRER LA PARTIE */ + ChoisirCouleurDessin(C_START); + RemplirRectangle(300, 500, 200, 50); + ChoisirCouleurDessin(CouleurParNom("white")); + draw_text_centered(300, 500, 200, 50, "DEMARRER", 2); +} + + +/* Gère l'interaction après un clic de souris */ +void menu_handle_mouse_click(menu_state_t *state) +{ + int i; + int x_click = _X; + int y_click = _Y; + int btn_size = BUTTON_SIZE; + int dim_section_x = IMG_START_X; + int button_l_offset = 180; + int button_c_offset = 400; + + /* 1. Clic sur les images */ + for (i = 0; i < NUM_IMAGES; i++) { + int x_img = IMG_START_X + i * IMG_SPACING; + int y_img = IMG_START_Y; + + if (is_in_rect(x_click, y_click, x_img, y_img, IMG_PREVIEW_SIZE, IMG_PREVIEW_SIZE)) { + state->selected_image = i; + return; + } + } + + /* 2. Clic sur les boutons de Lignes (+/-) */ + + /* + Lignes */ + if (is_in_rect(x_click, y_click, dim_section_x + button_l_offset, DIM_START_Y + 30, btn_size, btn_size)) { + if (state->rows < MAX_DIMENSION) state->rows++; + return; + } + + /* - Lignes */ + if (is_in_rect(x_click, y_click, dim_section_x + button_l_offset + 40, DIM_START_Y + 30, btn_size, btn_size)) { + if (state->rows > MIN_DIMENSION) state->rows--; + return; + } + + /* 3. Clic sur les boutons de Colonnes (+/-) */ + + /* + Colonnes */ + if (is_in_rect(x_click, y_click, dim_section_x + button_c_offset, DIM_START_Y + 30, btn_size, btn_size)) { + if (state->cols < MAX_DIMENSION) state->cols++; + return; + } + + /* - Colonnes */ + if (is_in_rect(x_click, y_click, dim_section_x + button_c_offset + 40, DIM_START_Y + 30, btn_size, btn_size)) { + if (state->cols > MIN_DIMENSION) state->cols--; + return; + } + + /* 4. Clic sur DÉMARRER */ + if (is_in_rect(x_click, y_click, 300, 500, 200, 50)) { + state->ready_to_play = 1; + return; + } +} + + +/* Gère l'interaction clavier */ +void menu_handle_key(menu_state_t *state) +{ + if (ToucheEnAttente()) { + int key = Touche(); + + if (key == XK_Escape) { + state->ready_to_play = -1; + } + else if (key == XK_Up) { + if (state->rows < MAX_DIMENSION) state->rows++; + } + else if (key == XK_Down) { + if (state->rows > MIN_DIMENSION) state->rows--; + } + else if (key == XK_Right) { + if (state->cols < MAX_DIMENSION) state->cols++; + } + else if (key == XK_Left) { + if (state->cols > MIN_DIMENSION) state->cols--; + } + else if (key == XK_Return) { + state->ready_to_play = 1; + } + } +} + +/* --- IMPLÉMENTATION DES UTILITAIRES PRIVÉS --- */ + +/* Vérifie si (x_click, y_click) est dans le rectangle */ +static int is_in_rect(int x_click, int y_click, int rx, int ry, int rw, int rh) +{ + return (x_click >= rx && x_click <= rx + rw && y_click >= ry && y_click <= ry + rh); +} + +/* Dessine un bouton rectangulaire rempli avec du texte centré */ +static void draw_button(int x, int y, const char *text, couleur C_BG) +{ + ChoisirCouleurDessin(C_BG); + RemplirRectangle(x, y, BUTTON_SIZE, BUTTON_SIZE); + ChoisirCouleurDessin(CouleurParNom("black")); + draw_text_centered(x, y, BUTTON_SIZE, BUTTON_SIZE, (char*)text, 1); +} + +/* Centre le texte dans une zone (x, y, w, h) */ +static void draw_text_centered(int x, int y, int w, int h, const char *text, int size) +{ + int text_w = TailleChaineEcran((char*)text, size); + int text_h_sup = TailleSupPolice(size); + /* Calcul de la position de départ pour centrer le texte */ + int draw_x = x + (w - text_w) / 2; + int draw_y = y + (h + text_h_sup) / 2; + + EcrireTexte(draw_x, draw_y, (char*)text, size); +} diff --git a/src/menu_view.h b/src/menu_view.h index e69de29..8f5f114 100644 --- a/src/menu_view.h +++ b/src/menu_view.h @@ -0,0 +1,24 @@ +/* src/menu_view.h */ + +#ifndef MENU_VIEW_H +#define MENU_VIEW_H + +#define NUM_IMAGES 3 +#define MIN_DIMENSION 3 +#define MAX_DIMENSION 8 + +/* Structure de l'état du menu */ +typedef struct { + int selected_image; /* Index de l'image (0, 1, ou 2) */ + int rows; /* Nombre de lignes (3 à 8) */ + int cols; /* Nombre de colonnes (3 à 8) */ + int ready_to_play; /* 1 si le joueur a validé */ +} menu_state_t; + +/* Prototypes des fonctions */ +void menu_init(menu_state_t *state); +void menu_render(const menu_state_t *state); +void menu_handle_mouse_click(menu_state_t *state); +void menu_handle_key(menu_state_t *state); + +#endif /* MENU_VIEW_H */