From 10373cd952daf99b79855100e07932a61a22a0d8 Mon Sep 17 00:00:00 2001 From: Pauline Froidure Date: Mon, 8 Dec 2025 16:19:03 +0100 Subject: [PATCH 01/17] feature: add new events functions to header file --- includes/cub3d.h | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/includes/cub3d.h b/includes/cub3d.h index b5df856..fb7e4ed 100644 --- a/includes/cub3d.h +++ b/includes/cub3d.h @@ -99,6 +99,25 @@ typedef struct s_orientation double plane_y; } t_orientation; +/* =========================== */ +/* EVENT */ +/* =========================== */ + +/* cleanup_exit.c */ +void cleanup_exit(t_game *game); + +/* events handlers.c */ + +/* player_actions_rotate.c */ +void rotate_left(t_game *game); +void rotate_right(t_game *game); + +/* player_actions_move.c */ +void move_forward(t_game *game); +void move_backward(t_game *game); +void strafe_left(t_game *game); +void strafe_right(t_game *game); + /* =========================== */ /* INIT */ /* =========================== */ @@ -142,6 +161,9 @@ void draw_pixel_in_buffer(t_game *game, int x, int y, int color); /* UTILS */ /* =========================== */ +/* ascii art */ +void print_ascii_art_hello(void); + /* utils/print_errors.c */ void print_errors(char *p1, char *p2, char *p3); From ba051aadc428b3b6c1eac8eea6b868f1e7c8170b Mon Sep 17 00:00:00 2001 From: Pauline Froidure Date: Mon, 8 Dec 2025 16:21:29 +0100 Subject: [PATCH 02/17] feature: code basic events related functions - cleanup function that cleans all the data when the user presses ESC key or click the red cross on top of the windows - prepare stub functions for player movements, for now, while waiting raycasting part, they log their action into the console --- src/events/.gitkeep | 0 src/events/cleanup_exit.c | 27 ++++++++++++++++++ src/events/events_handler.c | 2 ++ src/events/player actions_rotate.c | 23 +++++++++++++++ src/events/player_actions_move.c | 46 ++++++++++++++++++++++++++++++ 5 files changed, 98 insertions(+) delete mode 100644 src/events/.gitkeep create mode 100644 src/events/cleanup_exit.c create mode 100644 src/events/events_handler.c create mode 100644 src/events/player actions_rotate.c create mode 100644 src/events/player_actions_move.c diff --git a/src/events/.gitkeep b/src/events/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/src/events/cleanup_exit.c b/src/events/cleanup_exit.c new file mode 100644 index 0000000..1d32822 --- /dev/null +++ b/src/events/cleanup_exit.c @@ -0,0 +1,27 @@ +#include "cub3d.h" + +/** + * @brief Cleans up all game resources and exits program + * + * Destroys MLX resources (image, window, display) and frees game data. + * Called when user presses ESC or clicks window close button. + * + * @param game Pointer to game structure +*/ +void cleanup_exit(t_game *game) +{ + if (!game) + exit(EXIT_FAILURE); + if (game->img) + mlx_destroy_image(game->mlx, game->img); + if (game->win) + mlx_destroy_window(game->mlx, game->win); + if (game->mlx) + { + mlx_destroy_display(game->mlx); + free(game->mlx); + } + if (game->map.grid) + free_map(&game->map); + exit(EXIT_SUCCESS); +} diff --git a/src/events/events_handler.c b/src/events/events_handler.c new file mode 100644 index 0000000..72736fc --- /dev/null +++ b/src/events/events_handler.c @@ -0,0 +1,2 @@ +#include "cub3d.h" + diff --git a/src/events/player actions_rotate.c b/src/events/player actions_rotate.c new file mode 100644 index 0000000..f668b0a --- /dev/null +++ b/src/events/player actions_rotate.c @@ -0,0 +1,23 @@ +#include "cub3d.h" + +/** + * @brief Rotates camera to the left + * + * @param game Pointer to game structure +*/ +void rotate_left(t_game *game) +{ + (void)game; + printf("DEBUG: Rotating LEFT\n"); +} + +/** + * @brief Rotates camera to the right + * + * @param game Pointer to game structure +*/ +void rotate_right(t_game *game) +{ + (void)game; + printf("Rotating RIGHT\n"); +} diff --git a/src/events/player_actions_move.c b/src/events/player_actions_move.c new file mode 100644 index 0000000..df57cf3 --- /dev/null +++ b/src/events/player_actions_move.c @@ -0,0 +1,46 @@ +#include "cub3d.h" + +/** + * @brief Moves player forward in current direction + * + * @param game Pointer to game structure +*/ +void move_forward(t_game *game) +{ + (void)game; + printf(" DEBUG: Moving FORWARD\n"); +} + +/** + * @brief Moves player backward (opposite of current direction) + * + * @param game Pointer to game structure +*/ +void move_backward(t_game *game) +{ + (void)game; + printf("DEBUG: Moving BACKWARD\n"); +} + +/** + * @brief Strafes player to the left (perpendicular to direction) + * + * @param game Pointer to game structure +*/ +void strafe_left(t_game *game) +{ + (void)game; + printf("DEBUG: Strafing LEFT\n"); +} + +/** + * @brief Strafes player to the right (perpendicular to direction) + * + * @param game Pointer to game structure +*/ +void strafe_right(t_game *game) +{ + (void)game; + printf("DEBUG: Strafing RIGHT\n"); +} + From 3ed4d1cac5570be142c89df3cdf254af3cc4ea08 Mon Sep 17 00:00:00 2001 From: Pauline Froidure Date: Mon, 8 Dec 2025 16:22:21 +0100 Subject: [PATCH 03/17] feature: I know I can't help it: ASCII ART time it's very basic, I'll see what I can do better later --- src/utils/ascii_art.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 src/utils/ascii_art.c diff --git a/src/utils/ascii_art.c b/src/utils/ascii_art.c new file mode 100644 index 0000000..020fd2f --- /dev/null +++ b/src/utils/ascii_art.c @@ -0,0 +1,16 @@ +#include "cub3d.h" + +void print_ascii_art_hello(void) +{ + printf("Welcome to\n"); + printf(GRN); + printf(" ██████╗██╗ ██╗██████╗ ██████╗ ██████╗\n"); + printf("██╔════╝██║ ██║██╔══██╗╚════██╗██╔══██╗\n"); + printf("██║ ██║ ██║██████╔╝ █████╔╝██║ ██║\n"); + printf("██║ ██║ ██║██╔══██╗ ╚═══██╗██║ ██║\n"); + printf("╚██████╗╚██████╔╝██████╔╝██████╔╝██████╔╝\n"); + printf(" ╚═════╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚═════╝\n"); + printf(RESET); + printf("use WASD to move - left/right arrow to rotate camera\n"); + printf("press ESC or click the top right window cross to exit game\n\n"); +} From 0037c72a26259f828339a95fe6fb3e911105d9b8 Mon Sep 17 00:00:00 2001 From: Pauline Froidure Date: Mon, 8 Dec 2025 16:22:48 +0100 Subject: [PATCH 04/17] feature: add ascii art call to the main --- src/main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main.c b/src/main.c index 2cc95c7..f26f44d 100644 --- a/src/main.c +++ b/src/main.c @@ -16,6 +16,7 @@ int main(int argc, char **argv) return (EXIT_FAILURE); if (init_game_data(&game) != EXIT_SUCCESS) return (EXIT_FAILURE); + print_ascii_art_hello(); print_map_grid(&game.map); free_map(&game.map); return (EXIT_SUCCESS); From 0fb50936636f8eb1534827ede24e3482143b6c03 Mon Sep 17 00:00:00 2001 From: Pauline Froidure Date: Mon, 8 Dec 2025 16:23:32 +0100 Subject: [PATCH 05/17] feature: add new functions signature to makefile --- Makefile | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 50afafd..5f867bf 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ # ██║ ██║ ██║██████╔╝ █████╔╝██║ ██║ # ██║ ██║ ██║██╔══██╗ ╚═══██╗██║ ██║ # ╚██████╗╚██████╔╝██████╔╝██████╔╝██████╔╝ -# ╚═════╝ ╚═════╝ ╚═════╝ ╚ ╚═════╝ +# ╚═════╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚═════╝ # === general configuration === NAME = cub3D @@ -27,6 +27,10 @@ INC_DIR = -Iincludes -I$(LIBFT_DIR)/includes -I$(MLX_DIR) # === source files === SRC = src/main.c \ + src/events/cleanup_exit.c \ + src/events/events_handler.c \ + src/events/player_actions_rotate.c \ + src/events/player_actions_move.c \ src/init/init_data.c \ src/init/init_mlx.c \ src/parsing/file_validations.c \ @@ -35,6 +39,7 @@ SRC = src/main.c \ src/render/draw_pixels.c \ src/parsing/player_setup.c \ src/parsing/player_setup_utils.c \ + src/utils/ascii_art.c \ src/utils/print_errors.c \ # object files preserving subdirectory structure From 89f49a6d3239729d85569ad4d0eee10ab77b8b3c Mon Sep 17 00:00:00 2001 From: Pauline Froidure Date: Mon, 8 Dec 2025 22:51:51 +0100 Subject: [PATCH 06/17] feature: update header with handlers functions --- includes/cub3d.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/includes/cub3d.h b/includes/cub3d.h index fb7e4ed..4fc9bf2 100644 --- a/includes/cub3d.h +++ b/includes/cub3d.h @@ -107,6 +107,8 @@ typedef struct s_orientation void cleanup_exit(t_game *game); /* events handlers.c */ +int handle_keypress(int keycode, void *param); +int handle_close(void *param); /* player_actions_rotate.c */ void rotate_left(t_game *game); From 64087070e05cac67b40fdfbe9f5c63363636acc1 Mon Sep 17 00:00:00 2001 From: Pauline Froidure Date: Mon, 8 Dec 2025 22:52:49 +0100 Subject: [PATCH 07/17] feature: implement events handler and player stub movements --- src/events/events_handler.c | 46 +++++++++++++++++++ src/events/player_actions_move.c | 2 +- ...tions_rotate.c => player_actions_rotate.c} | 2 +- 3 files changed, 48 insertions(+), 2 deletions(-) rename src/events/{player actions_rotate.c => player_actions_rotate.c} (90%) diff --git a/src/events/events_handler.c b/src/events/events_handler.c index 72736fc..dce2518 100644 --- a/src/events/events_handler.c +++ b/src/events/events_handler.c @@ -1,2 +1,48 @@ #include "cub3d.h" +/** + * @brief Handles keyboard key press events + * + * Routes key presses to appropriate actions (movement, rotation, exit). + * + * @param keycode X11 keycode from event + * @param param Pointer to game structure (void* from MLX, must cast) + * @return 0/EXIT_SUCCESS (required by MLX) +*/ +int handle_keypress(int keycode, void *param) +{ + t_game *game; + + game = (t_game *)param; + if (keycode == XK_Escape) + cleanup_exit(game); + if (keycode == XK_w || keycode == XK_W) + move_forward(game); + else if (keycode == XK_s || keycode == XK_S) + move_backward(game); + else if (keycode == XK_a || keycode == XK_A) + strafe_left(game); + else if (keycode == XK_d || keycode == XK_D) + strafe_right(game); + else if (keycode == XK_Left) + rotate_left(game); + else if (keycode == XK_Right) + rotate_right(game); + return (EXIT_SUCCESS); +} + +/** + * @brief Handles window close button (red cross) event + * + * @param param Pointer to game structure (void* from MLX, must cast) + * @return 0/EXIT_SUCCESS (required by MLX) + */ +int handle_close(void *param) +{ + t_game *game; + + game = (t_game *)param; + cleanup_exit(game); + return (EXIT_SUCCESS); + +} diff --git a/src/events/player_actions_move.c b/src/events/player_actions_move.c index df57cf3..8b0c62b 100644 --- a/src/events/player_actions_move.c +++ b/src/events/player_actions_move.c @@ -8,7 +8,7 @@ void move_forward(t_game *game) { (void)game; - printf(" DEBUG: Moving FORWARD\n"); + printf("DEBUG: Moving FORWARD\n"); } /** diff --git a/src/events/player actions_rotate.c b/src/events/player_actions_rotate.c similarity index 90% rename from src/events/player actions_rotate.c rename to src/events/player_actions_rotate.c index f668b0a..924aa2f 100644 --- a/src/events/player actions_rotate.c +++ b/src/events/player_actions_rotate.c @@ -19,5 +19,5 @@ void rotate_left(t_game *game) void rotate_right(t_game *game) { (void)game; - printf("Rotating RIGHT\n"); + printf("DEBUG: Rotating RIGHT\n"); } From c0157a4269a769401e13df8b10c324b68a2e594d Mon Sep 17 00:00:00 2001 From: Pauline Froidure Date: Mon, 8 Dec 2025 22:53:21 +0100 Subject: [PATCH 08/17] feature: fix color in ascci art --- src/utils/ascii_art.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/utils/ascii_art.c b/src/utils/ascii_art.c index 020fd2f..c86a58e 100644 --- a/src/utils/ascii_art.c +++ b/src/utils/ascii_art.c @@ -3,7 +3,7 @@ void print_ascii_art_hello(void) { printf("Welcome to\n"); - printf(GRN); + printf(BR_GRN); printf(" ██████╗██╗ ██╗██████╗ ██████╗ ██████╗\n"); printf("██╔════╝██║ ██║██╔══██╗╚════██╗██╔══██╗\n"); printf("██║ ██║ ██║██████╔╝ █████╔╝██║ ██║\n"); @@ -11,6 +11,8 @@ void print_ascii_art_hello(void) printf("╚██████╗╚██████╔╝██████╔╝██████╔╝██████╔╝\n"); printf(" ╚═════╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚═════╝\n"); printf(RESET); + printf(BR_YEL); printf("use WASD to move - left/right arrow to rotate camera\n"); printf("press ESC or click the top right window cross to exit game\n\n"); + printf(RESET); } From b3f338b0c982f1c5009d681ce04eb02cf67c83dd Mon Sep 17 00:00:00 2001 From: Pauline Froidure Date: Mon, 8 Dec 2025 22:53:52 +0100 Subject: [PATCH 09/17] feature: implement key hook, cross hook and mlx loop --- src/main.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main.c b/src/main.c index f26f44d..65b94b3 100644 --- a/src/main.c +++ b/src/main.c @@ -19,5 +19,8 @@ int main(int argc, char **argv) print_ascii_art_hello(); print_map_grid(&game.map); free_map(&game.map); + mlx_key_hook(game.win, handle_keypress, &game); + mlx_hook(game.win, 17, 0, handle_close, &game); + mlx_loop(game.mlx); return (EXIT_SUCCESS); } From 7e48b6dff3ab18cb608f9807df8eff4a74a3064e Mon Sep 17 00:00:00 2001 From: Pauline Froidure Date: Mon, 8 Dec 2025 23:13:30 +0100 Subject: [PATCH 10/17] fix: fix issues in PR - missing else word - extra line to free in main - norm --- src/events/events_handler.c | 5 ++--- src/events/player_actions_move.c | 1 - src/main.c | 1 - 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/events/events_handler.c b/src/events/events_handler.c index dce2518..421d403 100644 --- a/src/events/events_handler.c +++ b/src/events/events_handler.c @@ -11,12 +11,12 @@ */ int handle_keypress(int keycode, void *param) { - t_game *game; + t_game *game; game = (t_game *)param; if (keycode == XK_Escape) cleanup_exit(game); - if (keycode == XK_w || keycode == XK_W) + else if (keycode == XK_w || keycode == XK_W) move_forward(game); else if (keycode == XK_s || keycode == XK_S) move_backward(game); @@ -44,5 +44,4 @@ int handle_close(void *param) game = (t_game *)param; cleanup_exit(game); return (EXIT_SUCCESS); - } diff --git a/src/events/player_actions_move.c b/src/events/player_actions_move.c index 8b0c62b..f438968 100644 --- a/src/events/player_actions_move.c +++ b/src/events/player_actions_move.c @@ -43,4 +43,3 @@ void strafe_right(t_game *game) (void)game; printf("DEBUG: Strafing RIGHT\n"); } - diff --git a/src/main.c b/src/main.c index 65b94b3..871977c 100644 --- a/src/main.c +++ b/src/main.c @@ -18,7 +18,6 @@ int main(int argc, char **argv) return (EXIT_FAILURE); print_ascii_art_hello(); print_map_grid(&game.map); - free_map(&game.map); mlx_key_hook(game.win, handle_keypress, &game); mlx_hook(game.win, 17, 0, handle_close, &game); mlx_loop(game.mlx); From 3421e77445378947aa180740e350e6846f815667 Mon Sep 17 00:00:00 2001 From: Pauline Froidure Date: Wed, 10 Dec 2025 09:55:41 +0100 Subject: [PATCH 11/17] refactor: change logic to movement reacting to key being released - now you don't have to spam the keys to advance, rotate, you keep the keys pressed and it will stop when you release the keys --- includes/cub3d.h | 17 ++++++++- src/events/events_handler.c | 60 ++++++++++++++++++++++-------- src/events/player_actions_move.c | 24 ++++++++++-- src/events/player_actions_rotate.c | 12 +++++- src/main.c | 4 +- 5 files changed, 94 insertions(+), 23 deletions(-) diff --git a/includes/cub3d.h b/includes/cub3d.h index 4fc9bf2..883e910 100644 --- a/includes/cub3d.h +++ b/includes/cub3d.h @@ -10,6 +10,7 @@ # include # include # include +# include /* =========================== */ /* DEFINE */ @@ -59,7 +60,18 @@ typedef struct s_map int ceiling_color; // rgb color for the ceiling, converted to int (0xRRGGBB) } t_map; -/* Represents the player’s state in the game */ +/* Tracks which keys are currently pressed */ +typedef struct s_keys +{ + bool w_pressed; + bool a_pressed; + bool s_pressed; + bool d_pressed; + bool left_arrow_pressed; + bool right_arrow_pressed; +} t_keys; + +/* Represents the player's state in the game */ typedef struct s_player { double pos_x; @@ -87,6 +99,7 @@ typedef struct s_game // === Game state === t_player player; // player data (position, direction, camera plane) t_map map; // map data (grid, size, textures paths, colors) + t_keys keys; // tracks which keys are currently pressed } t_game; /* player orientation struct for the look up table */ @@ -108,7 +121,9 @@ void cleanup_exit(t_game *game); /* events handlers.c */ int handle_keypress(int keycode, void *param); +int handle_keyrelease(int keycode, void *param); int handle_close(void *param); +int game_loop(void *param); /* player_actions_rotate.c */ void rotate_left(t_game *game); diff --git a/src/events/events_handler.c b/src/events/events_handler.c index 421d403..caafad3 100644 --- a/src/events/events_handler.c +++ b/src/events/events_handler.c @@ -1,14 +1,5 @@ #include "cub3d.h" -/** - * @brief Handles keyboard key press events - * - * Routes key presses to appropriate actions (movement, rotation, exit). - * - * @param keycode X11 keycode from event - * @param param Pointer to game structure (void* from MLX, must cast) - * @return 0/EXIT_SUCCESS (required by MLX) -*/ int handle_keypress(int keycode, void *param) { t_game *game; @@ -17,17 +8,37 @@ int handle_keypress(int keycode, void *param) if (keycode == XK_Escape) cleanup_exit(game); else if (keycode == XK_w || keycode == XK_W) - move_forward(game); + game->keys.w_pressed = true; else if (keycode == XK_s || keycode == XK_S) - move_backward(game); + game->keys.s_pressed = true; else if (keycode == XK_a || keycode == XK_A) - strafe_left(game); + game->keys.a_pressed = true; else if (keycode == XK_d || keycode == XK_D) - strafe_right(game); + game->keys.d_pressed = true; else if (keycode == XK_Left) - rotate_left(game); + game->keys.left_arrow_pressed = true; else if (keycode == XK_Right) - rotate_right(game); + game->keys.right_arrow_pressed = true; + return (EXIT_SUCCESS); +} + +int handle_keyrelease(int keycode, void *param) +{ + t_game *game; + + game = (t_game *)param; + if (keycode == XK_w || keycode == XK_W) + game->keys.w_pressed = false; + else if (keycode == XK_s || keycode == XK_S) + game->keys.s_pressed = false; + else if (keycode == XK_a || keycode == XK_A) + game->keys.a_pressed = false; + else if (keycode == XK_d || keycode == XK_D) + game->keys.d_pressed = false; + else if (keycode == XK_Left) + game->keys.left_arrow_pressed = false; + else if (keycode == XK_Right) + game->keys.right_arrow_pressed = false; return (EXIT_SUCCESS); } @@ -45,3 +56,22 @@ int handle_close(void *param) cleanup_exit(game); return (EXIT_SUCCESS); } + +int game_loop(void *param) +{ + t_game *game = (t_game *)param; + + if (game->keys.w_pressed) + move_forward(game); + if (game->keys.s_pressed) + move_backward(game); + if (game->keys.a_pressed) + strafe_left(game); + if (game->keys.d_pressed) + strafe_right(game); + if (game->keys.left_arrow_pressed) + rotate_left(game); + if (game->keys.right_arrow_pressed) + rotate_right(game); + return (EXIT_SUCCESS); +} diff --git a/src/events/player_actions_move.c b/src/events/player_actions_move.c index f438968..0501528 100644 --- a/src/events/player_actions_move.c +++ b/src/events/player_actions_move.c @@ -7,8 +7,12 @@ */ void move_forward(t_game *game) { + static int frame_count = 0; + (void)game; - printf("DEBUG: Moving FORWARD\n"); + frame_count++; + if (frame_count % 60 == 0) + printf("DEBUG: Moving FORWARD (frame %d)\n", frame_count); } /** @@ -18,8 +22,12 @@ void move_forward(t_game *game) */ void move_backward(t_game *game) { + static int frame_count = 0; + (void)game; - printf("DEBUG: Moving BACKWARD\n"); + frame_count++; + if (frame_count % 60 == 0) + printf("DEBUG: Moving BACKWARD (frame %d)\n", frame_count); } /** @@ -29,8 +37,12 @@ void move_backward(t_game *game) */ void strafe_left(t_game *game) { + static int frame_count = 0; + (void)game; - printf("DEBUG: Strafing LEFT\n"); + frame_count++; + if (frame_count % 60 == 0) + printf("DEBUG: Strafing LEFT (frame %d)\n", frame_count); } /** @@ -40,6 +52,10 @@ void strafe_left(t_game *game) */ void strafe_right(t_game *game) { + static int frame_count = 0; + (void)game; - printf("DEBUG: Strafing RIGHT\n"); + frame_count++; + if (frame_count % 60 == 0) + printf("DEBUG: Strafing RIGHT (frame %d)\n", frame_count); } diff --git a/src/events/player_actions_rotate.c b/src/events/player_actions_rotate.c index 924aa2f..35a6f6a 100644 --- a/src/events/player_actions_rotate.c +++ b/src/events/player_actions_rotate.c @@ -7,8 +7,12 @@ */ void rotate_left(t_game *game) { + static int frame_count = 0; + (void)game; - printf("DEBUG: Rotating LEFT\n"); + frame_count++; + if (frame_count % 60 == 0) + printf("DEBUG: Rotating LEFT (frame %d)\n", frame_count); } /** @@ -18,6 +22,10 @@ void rotate_left(t_game *game) */ void rotate_right(t_game *game) { + static int frame_count = 0; + (void)game; - printf("DEBUG: Rotating RIGHT\n"); + frame_count++; + if (frame_count % 60 == 0) + printf("DEBUG: Rotating RIGHT (frame %d)\n", frame_count); } diff --git a/src/main.c b/src/main.c index 871977c..17e2662 100644 --- a/src/main.c +++ b/src/main.c @@ -18,8 +18,10 @@ int main(int argc, char **argv) return (EXIT_FAILURE); print_ascii_art_hello(); print_map_grid(&game.map); - mlx_key_hook(game.win, handle_keypress, &game); + mlx_hook(game.win, 2, 1L<<0, handle_keypress, &game); + mlx_hook(game.win, 3, 1L<<1, handle_keyrelease, &game); mlx_hook(game.win, 17, 0, handle_close, &game); + mlx_loop_hook(game.mlx, game_loop, &game); mlx_loop(game.mlx); return (EXIT_SUCCESS); } From 9c8ca36efe8c3ff49f0720e32403f0d320f3cef9 Mon Sep 17 00:00:00 2001 From: Pauline Froidure Date: Wed, 10 Dec 2025 10:50:20 +0100 Subject: [PATCH 12/17] refactor: function pointers and no more if/else forest --- includes/cub3d.h | 59 +++++++++------- src/events/events_handler.c | 133 +++++++++++++++++++++++++----------- 2 files changed, 128 insertions(+), 64 deletions(-) diff --git a/includes/cub3d.h b/includes/cub3d.h index 883e910..ad0fb7e 100644 --- a/includes/cub3d.h +++ b/includes/cub3d.h @@ -37,7 +37,7 @@ /* game elements */ # define WINDOWS_X 800 # define WINDOWS_Y 600 -# define WINDOWS_MSG "Welcome to cub3D" +# define WINDOWS_MSG "Welcome to CUB3D" /* =========================== */ /* STRUCTURES */ @@ -112,76 +112,85 @@ typedef struct s_orientation double plane_y; } t_orientation; +/* key binding struct for mapping keys to actions */ +typedef struct s_key_binding +{ + int keycode; + void (*action)(t_game *); + bool *flag_ptr; +} t_key_binding; + /* =========================== */ /* EVENT */ /* =========================== */ /* cleanup_exit.c */ -void cleanup_exit(t_game *game); +void cleanup_exit(t_game *game); /* events handlers.c */ -int handle_keypress(int keycode, void *param); -int handle_keyrelease(int keycode, void *param); -int handle_close(void *param); -int game_loop(void *param); +int handle_keypress(int keycode, void *param); +int handle_keyrelease(int keycode, void *param); +int handle_close(void *param); +int game_loop(void *param); +t_key_binding *get_key_bindings(t_game *game); /* player_actions_rotate.c */ -void rotate_left(t_game *game); -void rotate_right(t_game *game); +void rotate_left(t_game *game); +void rotate_right(t_game *game); /* player_actions_move.c */ -void move_forward(t_game *game); -void move_backward(t_game *game); -void strafe_left(t_game *game); -void strafe_right(t_game *game); +void move_forward(t_game *game); +void move_backward(t_game *game); +void strafe_left(t_game *game); +void strafe_right(t_game *game); /* =========================== */ /* INIT */ /* =========================== */ /* init_data.c */ -void init_data(t_game *game); +void init_data(t_game *game); /* init_mlx.c */ -int init_game_data(t_game *game); +int init_game_data(t_game *game); /* =========================== */ /* PARSING */ /* =========================== */ /* file_validations.c */ -int validate_argument(char *filename); +int validate_argument(char *filename); /*parse_map.c */ -int parse_map(const char *path, t_map *map); +int parse_map(const char *path, t_map *map); /*parse_map_utils.c */ -int open_cub_file(const char *path); -void print_map_grid(t_map *map); -void free_map(t_map *map); -void free_partial_grid(t_map *map, int filled_rows); +int open_cub_file(const char *path); +void print_map_grid(t_map *map); +void free_map(t_map *map); +void free_partial_grid(t_map *map, int filled_rows); /* player_setup_utils.c */ -void print_player_info(t_player *player); +void print_player_info(t_player *player); /* player_setup.c */ -int init_player(t_game *game); +int init_player(t_game *game); /* =========================== */ /* RENDERS */ /* =========================== */ /* draw_pixels.c*/ -void draw_pixel_in_buffer(t_game *game, int x, int y, int color); +void draw_pixel_in_buffer(t_game *game, int x, int y, int color); /* =========================== */ /* UTILS */ /* =========================== */ /* ascii art */ -void print_ascii_art_hello(void); +void print_ascii_art_hello(void); /* utils/print_errors.c */ -void print_errors(char *p1, char *p2, char *p3); +void print_errors(char *p1, char *p2, char *p3); #endif diff --git a/src/events/events_handler.c b/src/events/events_handler.c index caafad3..7f3b7d7 100644 --- a/src/events/events_handler.c +++ b/src/events/events_handler.c @@ -1,44 +1,91 @@ #include "cub3d.h" +/** + * @brief Returns an array of key bindings mapping keycodes to actions + * + * This function returns a static array that maps X11 keycodes to their + * corresponding action functions and key state flags. + * + * @param game Pointer to game structure to access key flags + * @return Pointer to a static array of key bindings (NULL-terminated) + */ +t_key_binding *get_key_bindings(t_game *game) +{ + static t_key_binding bindings[7]; + + bindings[0] = (t_key_binding){XK_w, move_forward, &game->keys.w_pressed}; + bindings[1] = (t_key_binding){XK_s, move_backward, &game->keys.s_pressed}; + bindings[2] = (t_key_binding){XK_a, strafe_left, &game->keys.a_pressed}; + bindings[3] = (t_key_binding){XK_d, strafe_right, &game->keys.d_pressed}; + bindings[4] = (t_key_binding){XK_Left, rotate_left, + &game->keys.left_arrow_pressed}; + bindings[5] = (t_key_binding){XK_Right, rotate_right, + &game->keys.right_arrow_pressed}; + bindings[6] = (t_key_binding){0, NULL, NULL}; + return (bindings); +} + +/** + * @brief Handles key press events using function pointers + * + * Iterates through key bindings and sets the corresponding flag to true + * when a registered key is pressed. + * + * @param keycode X11 keycode of the pressed key + * @param param Pointer to game structure (void* from MLX, must cast) + * @return EXIT_SUCCESS + */ int handle_keypress(int keycode, void *param) { - t_game *game; + t_game *game; + const t_key_binding *bindings; + int i; game = (t_game *)param; if (keycode == XK_Escape) cleanup_exit(game); - else if (keycode == XK_w || keycode == XK_W) - game->keys.w_pressed = true; - else if (keycode == XK_s || keycode == XK_S) - game->keys.s_pressed = true; - else if (keycode == XK_a || keycode == XK_A) - game->keys.a_pressed = true; - else if (keycode == XK_d || keycode == XK_D) - game->keys.d_pressed = true; - else if (keycode == XK_Left) - game->keys.left_arrow_pressed = true; - else if (keycode == XK_Right) - game->keys.right_arrow_pressed = true; + bindings = get_key_bindings(game); + i = 0; + while (bindings[i].action) + { + if (bindings[i].keycode == keycode) + { + *bindings[i].flag_ptr = true; + return (EXIT_SUCCESS); + } + i++; + } return (EXIT_SUCCESS); } +/** + * @brief Handles key release events using function pointers + * + * Iterates through key bindings and sets the corresponding flag to false + * when a registered key is released. + * + * @param keycode X11 keycode of the released key + * @param param Pointer to game structure (void* from MLX, must cast) + * @return EXIT_SUCCESS + */ int handle_keyrelease(int keycode, void *param) { - t_game *game; + t_game *game; + t_key_binding *bindings; + int i; game = (t_game *)param; - if (keycode == XK_w || keycode == XK_W) - game->keys.w_pressed = false; - else if (keycode == XK_s || keycode == XK_S) - game->keys.s_pressed = false; - else if (keycode == XK_a || keycode == XK_A) - game->keys.a_pressed = false; - else if (keycode == XK_d || keycode == XK_D) - game->keys.d_pressed = false; - else if (keycode == XK_Left) - game->keys.left_arrow_pressed = false; - else if (keycode == XK_Right) - game->keys.right_arrow_pressed = false; + bindings = get_key_bindings(game); + i = 0; + while (bindings[i].action) + { + if (bindings[i].keycode == keycode) + { + *bindings[i].flag_ptr = false; + return (EXIT_SUCCESS); + } + i++; + } return (EXIT_SUCCESS); } @@ -57,21 +104,29 @@ int handle_close(void *param) return (EXIT_SUCCESS); } +/** + * @brief Main game loop - called every frame by MLX (~60 FPS) + * + * Checks which keys are pressed and calls their corresponding action + * functions using the key bindings system. + * + * @param param Pointer to game structure (void* from MLX, must cast) + * @return EXIT_SUCCESS + */ int game_loop(void *param) { - t_game *game = (t_game *)param; + t_game *game; + const t_key_binding *bindings; + int i; - if (game->keys.w_pressed) - move_forward(game); - if (game->keys.s_pressed) - move_backward(game); - if (game->keys.a_pressed) - strafe_left(game); - if (game->keys.d_pressed) - strafe_right(game); - if (game->keys.left_arrow_pressed) - rotate_left(game); - if (game->keys.right_arrow_pressed) - rotate_right(game); + game = (t_game *)param; + bindings = get_key_bindings(game); + i = 0; + while (bindings[i].action) + { + if (*bindings[i].flag_ptr) + bindings[i].action(game); + i++; + } return (EXIT_SUCCESS); } From 953f75eea781b02cca6960e45950520a18822716 Mon Sep 17 00:00:00 2001 From: Pauline Froidure Date: Wed, 10 Dec 2025 10:54:59 +0100 Subject: [PATCH 13/17] refactor: add documentation new structure for key_bindings explained --- includes/cub3d.h | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/includes/cub3d.h b/includes/cub3d.h index ad0fb7e..08fd454 100644 --- a/includes/cub3d.h +++ b/includes/cub3d.h @@ -100,6 +100,9 @@ typedef struct s_game t_player player; // player data (position, direction, camera plane) t_map map; // map data (grid, size, textures paths, colors) t_keys keys; // tracks which keys are currently pressed + // === Mouse === + int last_mouse_x; // last mouse X position for delta calculation + int last_mouse_y; // last mouse Y position for delta calculation } t_game; /* player orientation struct for the look up table */ @@ -115,9 +118,9 @@ typedef struct s_orientation /* key binding struct for mapping keys to actions */ typedef struct s_key_binding { - int keycode; - void (*action)(t_game *); - bool *flag_ptr; + int keycode; // X11 keycode for this specific key (ex: XK_w, XK_Left) + void (*action)(t_game *); // function pointer to the action that should be executed + bool *flag_ptr; // Pointer to the boolean flag that represents whether this key is currently pressed (true) or released (false) } t_key_binding; /* =========================== */ From 225b246414b7b840f3bd27f94b5e85bc7684eb80 Mon Sep 17 00:00:00 2001 From: Pauline Froidure Date: Wed, 10 Dec 2025 12:11:30 +0100 Subject: [PATCH 14/17] feature: mouse bonus implementation --- includes/cub3d.h | 6 ++++++ src/events/hooks.c | 9 +++++++++ src/events/mouse_handler.c | 40 ++++++++++++++++++++++++++++++++++++++ src/init/init_data.c | 3 +++ src/main.c | 4 +--- 5 files changed, 59 insertions(+), 3 deletions(-) create mode 100644 src/events/hooks.c create mode 100644 src/events/mouse_handler.c diff --git a/includes/cub3d.h b/includes/cub3d.h index 08fd454..74188fd 100644 --- a/includes/cub3d.h +++ b/includes/cub3d.h @@ -137,6 +137,12 @@ int handle_close(void *param); int game_loop(void *param); t_key_binding *get_key_bindings(t_game *game); +/* mouse_handler.c */ +int handle_mouse_move(int x, int y, void *param); + +/* hooks.c */ +void setup_hooks(t_game *game); + /* player_actions_rotate.c */ void rotate_left(t_game *game); void rotate_right(t_game *game); diff --git a/src/events/hooks.c b/src/events/hooks.c new file mode 100644 index 0000000..c3fd033 --- /dev/null +++ b/src/events/hooks.c @@ -0,0 +1,9 @@ +#include "cub3d.h" + +void setup_hooks(t_game *game) +{ + mlx_hook(game->win, 2, 1L << 0, handle_keypress, game); + mlx_hook(game->win, 3, 1L << 1, handle_keyrelease, game); + mlx_hook(game->win, 17, 0, handle_close, game); + mlx_hook(game->win, 6, 1L << 6, handle_mouse_move, game); +} diff --git a/src/events/mouse_handler.c b/src/events/mouse_handler.c new file mode 100644 index 0000000..6b3f4e0 --- /dev/null +++ b/src/events/mouse_handler.c @@ -0,0 +1,40 @@ +#include "cub3d.h" + +/** + * @brief Handles mouse movement for horizontal camera rotation (stub) + * + * Detects horizontal mouse movement and logs rotation direction. + * Only handles left/right rotation (yaw), not up/down (pitch). + * Currently just logs debug messages, actual rotation logic to be implemented. + * + * @param x Current mouse X position in window coordinates + * @param y Current mouse Y position in window coordinates + * @param param Pointer to game structure (void* from MLX, must cast) + * @return EXIT_SUCCESS + */ +int handle_mouse_move(int x, int y, void *param) +{ + static int frame_count_left = 0; + static int frame_count_right = 0; + t_game *game; + int delta_x; + + game = (t_game *)param; + delta_x = x - game->last_mouse_x; + if (delta_x > 0) + { + frame_count_right++; + if (frame_count_right % 60 == 0) + printf("DEBUG: Mouse rotating RIGHT (frame %d)\n", + frame_count_right); + } + else if (delta_x < 0) + { + frame_count_left++; + if (frame_count_left % 60 == 0) + printf("DEBUG: Mouse rotating LEFT (frame %d)\n", frame_count_left); + } + game->last_mouse_x = x; + game->last_mouse_y = y; + return (EXIT_SUCCESS); +} diff --git a/src/init/init_data.c b/src/init/init_data.c index fdc18b1..1cafc73 100644 --- a/src/init/init_data.c +++ b/src/init/init_data.c @@ -16,4 +16,7 @@ void init_data(t_game *game) return ; // Zero out entire struct including any nested structs and its fields ft_bzero(game, sizeof(t_game)); + // Initialize mouse position to center of window + game->last_mouse_x = WINDOWS_X / 2; + game->last_mouse_y = WINDOWS_Y / 2; } diff --git a/src/main.c b/src/main.c index 17e2662..b9e18d1 100644 --- a/src/main.c +++ b/src/main.c @@ -18,9 +18,7 @@ int main(int argc, char **argv) return (EXIT_FAILURE); print_ascii_art_hello(); print_map_grid(&game.map); - mlx_hook(game.win, 2, 1L<<0, handle_keypress, &game); - mlx_hook(game.win, 3, 1L<<1, handle_keyrelease, &game); - mlx_hook(game.win, 17, 0, handle_close, &game); + setup_hooks(&game); mlx_loop_hook(game.mlx, game_loop, &game); mlx_loop(game.mlx); return (EXIT_SUCCESS); From 7bb1d01f90b55d76bf3aac13a003404ab40df001 Mon Sep 17 00:00:00 2001 From: Pauline Froidure Date: Wed, 10 Dec 2025 12:12:43 +0100 Subject: [PATCH 15/17] feature: update makefile with mouse handling functions --- Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Makefile b/Makefile index 5f867bf..382b97b 100644 --- a/Makefile +++ b/Makefile @@ -29,8 +29,10 @@ INC_DIR = -Iincludes -I$(LIBFT_DIR)/includes -I$(MLX_DIR) SRC = src/main.c \ src/events/cleanup_exit.c \ src/events/events_handler.c \ + src/events/hooks.c \ src/events/player_actions_rotate.c \ src/events/player_actions_move.c \ + src/events/mouse_handler.c \ src/init/init_data.c \ src/init/init_mlx.c \ src/parsing/file_validations.c \ From 93d232078d34f0e4bbcc0e38018f419ddca44f0a Mon Sep 17 00:00:00 2001 From: Pauline Froidure Date: Wed, 10 Dec 2025 14:09:00 +0100 Subject: [PATCH 16/17] fix: add missing cleanup function in main --- src/main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main.c b/src/main.c index b9e18d1..90fc97d 100644 --- a/src/main.c +++ b/src/main.c @@ -21,5 +21,6 @@ int main(int argc, char **argv) setup_hooks(&game); mlx_loop_hook(game.mlx, game_loop, &game); mlx_loop(game.mlx); + cleanup_exit(&game); return (EXIT_SUCCESS); } From dda6de3292012daa4657a9552c09994378c6c32a Mon Sep 17 00:00:00 2001 From: Pauline Froidure Date: Wed, 10 Dec 2025 16:05:09 +0100 Subject: [PATCH 17/17] fix: last fix before merge - remove const on a struct (no need) - add doxygen com --- src/events/events_handler.c | 2 +- src/events/hooks.c | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/events/events_handler.c b/src/events/events_handler.c index 7f3b7d7..84edae2 100644 --- a/src/events/events_handler.c +++ b/src/events/events_handler.c @@ -116,7 +116,7 @@ int handle_close(void *param) int game_loop(void *param) { t_game *game; - const t_key_binding *bindings; + t_key_binding *bindings; int i; game = (t_game *)param; diff --git a/src/events/hooks.c b/src/events/hooks.c index c3fd033..b27ba14 100644 --- a/src/events/hooks.c +++ b/src/events/hooks.c @@ -1,5 +1,14 @@ #include "cub3d.h" +/** + * @brief Registers all event hooks for the game window. + * + * Sets up keyboard press/release events, window close event, + * and mouse movement handling. These functions allow the game + * to react to player inputs during runtime. + * + * @param game Pointer to the game structure containing MLX window. + */ void setup_hooks(t_game *game) { mlx_hook(game->win, 2, 1L << 0, handle_keypress, game);