This commit is contained in:
lecointre
2025-12-01 22:10:36 +01:00
parent 99cb83582a
commit 9b3c3fcec3
8 changed files with 225 additions and 23 deletions
+4 -2
View File
@@ -6,8 +6,8 @@ CFLAGS = -Wall -Wextra -std=c89
LDFLAGS = -lgraph
TARGET = taquin
# Liste de tous les fichiers sources (.c)
SRCS = src/main.c src/menu_view.c src/game_logic.c src/images.c src/utils.c
# Liste de tous les fichiers sources (.c) - INCLUT TOUS LES MODULES
SRCS = src/main.c src/menu_view.c src/game_logic.c src/images.c src/utils.c src/game_view.c
# Liste de tous les fichiers objets (.o) correspondants
OBJS = $(patsubst src/%.c, obj/%.o, $(SRCS))
@@ -38,3 +38,5 @@ run: $(TARGET)
# Nettoyage
clean:
@rm -rf obj $(TARGET)
.PHONY : all clean run
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
+12
View File
@@ -0,0 +1,12 @@
/* src/defs.h
* Définitions des constantes globales (taille de fenêtre, cycles).
* Inclus par main.c et game_view.c.
*/
#ifndef DEFS_H
#define DEFS_H
#define WINDOW_WIDTH 800
#define WINDOW_HEIGHT 600
#define REFRESH_CYCLE 50000L /* 50 ms */
#endif /* DEFS_H */
+182
View File
@@ -0,0 +1,182 @@
/* src/game_view.c
* Implémentation du rendu graphique du plateau et de la boucle d'interaction.
*/
#include "game_view.h"
#include <graph.h>
#include <stdio.h>
#include <stdlib.h>
/* Constantes et variables globales (définies dans d'autres modules ou par l'IUT) */
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 tuile donnée */
static int is_in_tile_rect(int x_click, int y_click, int tile_x, int tile_y, int tile_w, int tile_h)
{
return (x_click >= tile_x && x_click <= tile_x + tile_w &&
y_click >= tile_y && y_click <= tile_y + tile_h);
}
/* --- Fonctions de Rendu et de Logique --- */
/* Dessine le plateau de jeu */
void game_render(const game_state_t *state)
{
int i, r, c;
couleur C_FOND = CouleurParNom("gray");
couleur C_BORDURE = CouleurParNom("black");
EffacerEcran(C_FOND);
/* On prend la taille des tuiles calculée lors du découpage */
int tile_display_w = state->all_tiles[0]->width;
int tile_display_h = state->all_tiles[0]->height;
ChoisirCouleurDessin(C_BORDURE);
/* Boucle sur toutes les cases du plateau */
for (i = 0; i < state->rows * state->cols; i++) {
int tile_id = state->permutation[i];
int x_pos, y_pos;
r = i / state->cols;
c = i % state->cols;
/* Position d'affichage sur l'écran */
x_pos = MARGIN + c * tile_display_w;
y_pos = MARGIN + r * tile_display_h;
if (tile_id != -1) { /* C'est une tuile (non vide) */
tile_t *current_tile = state->all_tiles[tile_id];
/* ChargerImage(fichier, x_dst, y_dst, x_src, y_src, l, h) */
ChargerImage(current_tile->path,
x_pos, y_pos,
current_tile->src_x, current_tile->src_y,
current_tile->width, current_tile->height);
/* Dessine la bordure */
DessinerRectangle(x_pos, y_pos, tile_display_w, tile_display_h);
} else {
/* Dessine la case vide en couleur distincte (jaune) */
ChoisirCouleurDessin(CouleurParNom("yellow"));
RemplirRectangle(x_pos, y_pos, tile_display_w, tile_display_h);
ChoisirCouleurDessin(C_BORDURE);
DessinerRectangle(x_pos, y_pos, tile_display_w, tile_display_h);
}
}
/* Affichage du compteur de coups */
char buffer[100];
sprintf(buffer, "Coups: %lu", state->moves);
EcrireTexte(MARGIN, WINDOW_HEIGHT - 30, buffer, 1);
/* Affichage de la victoire */
if (state->is_solved) {
ChoisirCouleurDessin(CouleurParNom("red"));
EcrireTexte(WINDOW_WIDTH / 2 - 100, WINDOW_HEIGHT / 2, "BRAVO ! PRESSEZ UNE TOUCHE.", 2);
}
}
/* Gère les entrées (clic/clavier) et la boucle principale du jeu */
void game_loop(game_state_t *state)
{
unsigned long next_update = Microsecondes() + REFRESH_CYCLE;
int go_on = 1;
while (go_on && !state->is_solved)
{
/* Rendu et rafraîchissement */
if (Microsecondes() > next_update)
{
game_render(state);
CopierZone(0, 0, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, 0, 0);
next_update = Microsecondes() + REFRESH_CYCLE;
}
/* Gestion des événements Souris */
if (SourisCliquee())
{
int i;
int x_click = _X;
int y_click = _Y;
int tile_w = state->all_tiles[0]->width;
int tile_h = state->all_tiles[0]->height;
/* Parcourir toutes les tuiles pour voir laquelle a été cliquée */
for (i = 0; i < state->rows * state->cols; i++) {
int r = i / state->cols;
int c = i % state->cols;
int x_pos = MARGIN + c * tile_w;
int y_pos = MARGIN + r * tile_h;
if (is_in_tile_rect(x_click, y_click, x_pos, y_pos, tile_w, tile_h)) {
/* Tenter de déplacer la tuile cliquée (indice i) */
game_move_tile(state, i);
break;
}
}
}
/* 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;
if (key == XK_Escape) {
go_on = 0;
}
/* CORRECTION FINALE : Inverse le mapping de commande pour la perception intuitive */
else if (key == XK_Up) {
/* Le joueur appuie HAUT (monte) -> la tuile en BAS (r+1) doit monter */
target_index = (empty_r + 1) * state->cols + empty_c;
} else if (key == XK_Down) {
/* Le joueur appuie BAS (descend) -> la tuile en HAUT (r-1) doit descendre */
target_index = (empty_r - 1) * state->cols + empty_c;
}
else if (key == XK_Left) {
/* Le joueur appuie GAUCHE -> la tuile à DROITE (c+1) va à gauche */
target_index = empty_r * state->cols + (empty_c + 1);
} else if (key == XK_Right) {
/* Le joueur appuie DROITE -> la tuile à GAUCHE (c-1) va à droite */
target_index = empty_r * state->cols + (empty_c - 1);
}
/* Tenter le mouvement s'il y a une cible */
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) {
game_render(state);
CopierZone(0, 0, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, 0, 0);
printf("BRAVO ! Partie terminee en %lu coups. Pressez 'N' pour Nouvelle Partie ou 'Q' pour Quitter.\n", state->moves);
/* Gère le choix de rejouer/quitter après la victoire */
while (1) {
if (ToucheEnAttente()) {
int key = Touche();
if (key == 'n' || key == 'N') {
return; /* Retourne au main pour relancer le menu */
} else if (key == 'q' || key == 'Q') {
exit(EXIT_SUCCESS); /* Quitte le programme entier */
}
}
Microsecondes();
}
}
}
+16
View File
@@ -0,0 +1,16 @@
/* src/game_view.h
* Définitions du module de la vue du plateau de jeu.
*/
#ifndef GAME_VIEW_H
#define GAME_VIEW_H
#include "game_logic.h"
#include "defs.h" /* Nécessaire pour les constantes de fenêtre */
/* Dessine le plateau de jeu, les tuiles à leur position actuelle, et le compteur de coups. */
void game_render(const game_state_t *state);
/* Gère la boucle principale du jeu, les événements (clics/clavier) et les rafraîchissements. */
void game_loop(game_state_t *state);
#endif /* GAME_VIEW_H */
+11 -21
View File
@@ -4,20 +4,14 @@
*/
#include "menu_view.h"
#include "game_logic.h" /* Nouveau: pour initialiser le jeu */
#include "images.h" /* Nouveau: pour le chargement des tuiles */
#include "utils.h" /* Nouveau: pour l'aléatoire */
#include "game_logic.h"
#include "images.h"
#include "game_view.h" /* NOUVEAU: Pour la boucle de jeu */
#include "defs.h" /* NOUVEAU: Pour les constantes de fenêtre */
#include <graph.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h> /* Pour srand() */
/* Constantes de la fenêtre */
#define WINDOW_WIDTH 800
#define WINDOW_HEIGHT 600
/* Temps de rafraîchissement (pour économiser le CPU) */
#define REFRESH_CYCLE 50000L /* 50 ms */
#include <time.h>
int main(void)
{
@@ -28,9 +22,7 @@ int main(void)
InitialiserGraphique();
CreerFenetre(10, 10, WINDOW_WIDTH, WINDOW_HEIGHT);
/* Initialisation du générateur aléatoire (OBLIGATOIRE pour game_shuffle) */
srand((unsigned int)time(NULL));
menu_init(&menu_state);
next_update = Microsecondes() + REFRESH_CYCLE;
@@ -41,7 +33,6 @@ int main(void)
if (Microsecondes() > next_update)
{
menu_render(&menu_state);
/* Force l'affichage */
CopierZone(0, 0, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, 0, 0);
next_update = Microsecondes() + REFRESH_CYCLE;
}
@@ -54,7 +45,7 @@ int main(void)
menu_handle_key(&menu_state);
}
/* 3. Transition vers le jeu ou sortie */
/* 3. Transition vers le jeu */
if (menu_state.ready_to_play == 1) {
image_source_t img_src;
@@ -62,22 +53,21 @@ int main(void)
game_state_t game_state;
int num_tiles = menu_state.rows * menu_state.cols;
/* 3.1. Préparation des données et allocation */
/* Préparation des données et initialisation du moteur de jeu */
img_src = get_image_source(menu_state.selected_image);
tiles = images_slice(img_src, menu_state.rows, menu_state.cols);
/* Initialisation du jeu */
game_init(&game_state, menu_state.rows, menu_state.cols, tiles);
/* Mélange (Partie 3) */
/* Mélange le plateau */
game_shuffle_safe(&game_state, 500);
printf("DEBUG: Jeu prêt. Grille %d x %d melangee. Lancement de la boucle de jeu...\n",
game_state.rows, game_state.cols);
/* TODO: Boucle de JEU (GRANDE PARTIE 3) */
/* Lancement de la BOUCLE DE JEU */
game_loop(&game_state);
/* 3.2. Nettoyage après la fin de la partie */
/* Nettoyage final (après que le joueur a fini de jouer) */
images_free_tiles(tiles, num_tiles);
game_free(&game_state);
}
BIN
View File
Binary file not shown.