Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 19926dfcab | |||
| ff7259159c |
|
Before Width: | Height: | Size: 426 KiB |
|
After Width: | Height: | Size: 871 KiB |
|
After Width: | Height: | Size: 48 KiB |
|
After Width: | Height: | Size: 254 KiB |
|
After Width: | Height: | Size: 78 KiB |
|
After Width: | Height: | Size: 326 KiB |
|
After Width: | Height: | Size: 44 KiB |
|
After Width: | Height: | Size: 150 KiB |
|
Before Width: | Height: | Size: 161 KiB After Width: | Height: | Size: 150 KiB |
|
After Width: | Height: | Size: 558 KiB |
|
After Width: | Height: | Size: 47 KiB |
@@ -1,5 +1,6 @@
|
||||
/* src/game_view.c
|
||||
* Implémentation du rendu graphique du plateau et de la boucle d'interaction.
|
||||
* FIX CRITIQUE: La logique clavier est maintenant implémentée en interne (solution de fusion).
|
||||
*/
|
||||
|
||||
#include "game_view.h"
|
||||
@@ -11,7 +12,6 @@ extern int _X;
|
||||
extern int _Y;
|
||||
#define MARGIN 50 /* Marge autour du plateau */
|
||||
|
||||
|
||||
/* --- Fonctions Utilitaires Privées --- */
|
||||
|
||||
/* Vérifie si un clic est sur une zone rectangulaire donnée */
|
||||
@@ -21,6 +21,35 @@ static int is_in_tile_rect(int x_click, int y_click, int tile_x, int tile_y, int
|
||||
y_click >= tile_y && y_click <= tile_y + tile_h);
|
||||
}
|
||||
|
||||
/* * CRITICAL FIX: Logique du déplacement clavier (Implémentation interne pour résoudre la liaison).
|
||||
* C'est cette fonction qui était mal liée.
|
||||
*/
|
||||
static int get_tile_to_move_internal(const game_state_t *state, int key)
|
||||
{
|
||||
int empty_r = state->empty_index / state->cols;
|
||||
int empty_c = state->empty_index % state->cols;
|
||||
int target_r = empty_r;
|
||||
int target_c = empty_c;
|
||||
|
||||
if (key == XK_Up) {
|
||||
target_r = empty_r + 1; /* Tuile en BAS monte */
|
||||
} else if (key == XK_Down) {
|
||||
target_r = empty_r - 1; /* Tuile en HAUT descend */
|
||||
} else if (key == XK_Left) {
|
||||
target_c = empty_c + 1; /* Tuile à DROITE va à gauche */
|
||||
} else if (key == XK_Right) {
|
||||
target_c = empty_c - 1; /* Tuile à GAUCHE va à droite */
|
||||
} else {
|
||||
return -1; /* Touche non supportée */
|
||||
}
|
||||
|
||||
if (target_r >= 0 && target_r < state->rows && target_c >= 0 && target_c < state->cols) {
|
||||
return target_r * state->cols + target_c;
|
||||
}
|
||||
return -1; /* Hors bordure */
|
||||
}
|
||||
|
||||
|
||||
/* --- Fonctions de Rendu et de Logique --- */
|
||||
|
||||
/* Dessine le plateau de jeu */
|
||||
@@ -36,6 +65,9 @@ void game_render(const game_state_t *state)
|
||||
int tile_display_w = state->all_tiles[0]->width;
|
||||
int tile_display_h = state->all_tiles[0]->height;
|
||||
|
||||
/* Calcul des dimensions du plateau */
|
||||
int board_width = state->cols * tile_display_w;
|
||||
|
||||
ChoisirCouleurDessin(C_BORDURE);
|
||||
|
||||
/* 1. Affichage du Plateau (Tuiles et Case Vide) */
|
||||
@@ -95,11 +127,14 @@ void game_render(const game_state_t *state)
|
||||
EcrireTexte(MARGIN, WINDOW_HEIGHT - 30, buffer, 1);
|
||||
|
||||
/* 4. Bouton Retour Menu */
|
||||
int btn_w = 150;
|
||||
int btn_h = 40;
|
||||
|
||||
int btn_x = WINDOW_WIDTH - 200;
|
||||
int btn_y = WINDOW_HEIGHT - 60;
|
||||
|
||||
ChoisirCouleurDessin(CouleurParNom("orange"));
|
||||
RemplirRectangle(btn_x, btn_y, 150, 40);
|
||||
RemplirRectangle(btn_x, btn_y, btn_w, btn_h);
|
||||
ChoisirCouleurDessin(CouleurParNom("black"));
|
||||
EcrireTexte(btn_x + 10, btn_y + 25, "MENU (R)", 1);
|
||||
|
||||
@@ -138,7 +173,7 @@ void game_loop(game_state_t *state)
|
||||
|
||||
/* Vérifier le bouton RETOUR MENU */
|
||||
if (is_in_tile_rect(x_click, y_click, WINDOW_WIDTH - 200, WINDOW_HEIGHT - 60, 150, 40)) {
|
||||
go_on = 0; /* Quitte la boucle de jeu pour revenir au menu */
|
||||
go_on = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -161,40 +196,24 @@ void game_loop(game_state_t *state)
|
||||
/* Gestion des événements Clavier */
|
||||
if (ToucheEnAttente()) {
|
||||
int key = Touche();
|
||||
|
||||
int target_index = -1;
|
||||
int empty_r = state->empty_index / state->cols;
|
||||
int empty_c = state->empty_index % state->cols;
|
||||
int target_index;
|
||||
|
||||
if (key == XK_Escape) {
|
||||
exit(EXIT_SUCCESS); /* Quitte l'application entièrement si ESC */
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
/* Touche 'R' pour revenir au menu (Nouvelle Partie) */
|
||||
else if (key == 'r' || key == 'R') {
|
||||
go_on = 0;
|
||||
}
|
||||
/* Logique de déplacement Clavier (corrigée) */
|
||||
else if (key == XK_Up) {
|
||||
/* HAUT : Déplace la tuile en BAS (r + 1) vers le vide (r) */
|
||||
target_index = (empty_r + 1) * state->cols + empty_c;
|
||||
} else if (key == XK_Down) {
|
||||
/* BAS : Déplace la tuile en HAUT (r - 1) vers le vide (r) */
|
||||
target_index = (empty_r - 1) * state->cols + empty_c;
|
||||
}
|
||||
else if (key == XK_Left) {
|
||||
/* GAUCHE : Déplace la tuile à DROITE (c + 1) vers le vide (c) */
|
||||
target_index = empty_r * state->cols + (empty_c + 1);
|
||||
} else if (key == XK_Right) {
|
||||
/* DROITE : Déplace la tuile à GAUCHE (c - 1) vers le vide (c) */
|
||||
target_index = empty_r * state->cols + (empty_c - 1);
|
||||
}
|
||||
|
||||
/* Tenter le mouvement s'il y a une cible */
|
||||
/* Logique de déplacement Clavier simplifiée via la fonction interne */
|
||||
else {
|
||||
target_index = get_tile_to_move_internal(state, key);
|
||||
if (target_index != -1) {
|
||||
game_move_tile(state, target_index);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Si la boucle est terminée par la victoire ou ESC */
|
||||
if (state->is_solved) {
|
||||
|
||||
@@ -8,10 +8,17 @@
|
||||
#include <string.h>
|
||||
|
||||
/* Tableau statique des chemins d'images disponibles (synchronisé avec l'ordre du menu) */
|
||||
static const char *IMAGE_PATHS[] = {
|
||||
"assets/spiderman.jpg", /* Index 0 */
|
||||
"assets/capy.jpg", /* Index 1 */
|
||||
"assets/iut.jpg" /* Index 2 */
|
||||
static const char *IMAGE_PATHS_FULL[] = {
|
||||
"assets/spiderman.png", /* Index 0 */
|
||||
"assets/capy.png", /* Index 1 */
|
||||
"assets/iut.png" /* Index 2 */
|
||||
};
|
||||
|
||||
/* Tableau statique des chemins des images OPTIMISÉES (pour l'APERÇU MENU) */
|
||||
static const char *IMAGE_PATHS_PREVIEW[] = {
|
||||
"assets/spiderman_small.png",
|
||||
"assets/capy_small.png",
|
||||
"assets/iut_small.png"
|
||||
};
|
||||
|
||||
|
||||
@@ -22,27 +29,35 @@ image_source_t get_image_source(int selected_index)
|
||||
|
||||
/* 1. Définition du chemin selon l'index */
|
||||
if (selected_index >= 0 && selected_index < 3) {
|
||||
strcpy(src.path, IMAGE_PATHS[selected_index]);
|
||||
strcpy(src.path, IMAGE_PATHS_FULL[selected_index]);
|
||||
} else {
|
||||
strcpy(src.path, IMAGE_PATHS[0]); /* Fallback */
|
||||
strcpy(src.path, IMAGE_PATHS_FULL[0]); /* Fallback */
|
||||
}
|
||||
|
||||
/* 2. DÉFINITION DES TAILLES RÉELLES (Utilisation des données 'identify') */
|
||||
if (selected_index == 0) {
|
||||
/* Spiderman (720x720) */
|
||||
src.width = 720;
|
||||
src.height = 720;
|
||||
src.height = 560;
|
||||
} else if (selected_index == 1) {
|
||||
/* Capybara (1000x662) */
|
||||
src.width = 1000;
|
||||
src.height = 662;
|
||||
src.width = 720;
|
||||
src.height = 560;
|
||||
} else { /* Index 2 */
|
||||
/* IUT (1200x800) */
|
||||
src.width = 1200;
|
||||
src.height = 800;
|
||||
src.width = 720;
|
||||
src.height = 560;
|
||||
}
|
||||
|
||||
/* 3. ASSURER LA DIVISIBILITÉ PAR 8 (Ajustement pour le découpage propre) */
|
||||
|
||||
/* 3. Définition du chemin pour l'APERÇU (Utilisé par menu_view.c) */
|
||||
if (selected_index >= 0 && selected_index < 3) {
|
||||
strcpy(src.preview_path, IMAGE_PATHS_PREVIEW[selected_index]);
|
||||
} else {
|
||||
strcpy(src.preview_path, IMAGE_PATHS_PREVIEW[0]);
|
||||
}
|
||||
|
||||
/* 4. ASSURER LA DIVISIBILITÉ PAR 8 (Ajustement pour le découpage propre) */
|
||||
/* On retire le reste de la division (modulo 8) pour éviter les erreurs de bordure. */
|
||||
src.width = src.width - (src.width % 8);
|
||||
src.height = src.height - (src.height % 8);
|
||||
|
||||
@@ -19,6 +19,7 @@ typedef struct {
|
||||
int width;
|
||||
int height;
|
||||
char path[30];
|
||||
char preview_path[30];
|
||||
} image_source_t;
|
||||
|
||||
/* Prototypes */
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include "menu_view.h"
|
||||
#include "defs.h"
|
||||
#include "images.h"
|
||||
#include <graph.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -49,8 +50,8 @@ void menu_render(const menu_state_t *state)
|
||||
couleur C_BOUTON = CouleurParNom("dark gray");
|
||||
couleur C_START = CouleurParNom("green");
|
||||
char buffer[50];
|
||||
|
||||
char path_buffer[30];
|
||||
image_source_t current_src;
|
||||
|
||||
EffacerEcran(C_FOND);
|
||||
ChoisirCouleurDessin(C_TEXTE);
|
||||
@@ -64,14 +65,18 @@ void menu_render(const menu_state_t *state)
|
||||
int x = IMG_START_X + i * IMG_SPACING;
|
||||
int y = IMG_START_Y;
|
||||
|
||||
/* Définition du chemin */
|
||||
/* Définition du chemin
|
||||
if (i == 0) {
|
||||
strcpy(path_buffer, "assets/spiderman.jpg");
|
||||
strcpy(path_buffer, "assets/spiderman_small.png");
|
||||
} else if (i == 1) {
|
||||
strcpy(path_buffer, "assets/capy.jpg");
|
||||
strcpy(path_buffer, "assets/capy_small.png");
|
||||
} else {
|
||||
strcpy(path_buffer, "assets/iut.jpg");
|
||||
}
|
||||
strcpy(path_buffer, "assets/iut_small.png");
|
||||
}*/
|
||||
|
||||
/* OBTENIR LE CHEMIN OPTIMISÉ */
|
||||
current_src = get_image_source(i);
|
||||
strcpy(path_buffer, current_src.preview_path);
|
||||
|
||||
/* Affiche l'image */
|
||||
ChargerImage(path_buffer,
|
||||
|
||||