Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# ██║ ██║ ██║██████╔╝ █████╔╝██║ ██║
# ██║ ██║ ██║██╔══██╗ ╚═══██╗██║ ██║
# ╚██████╗╚██████╔╝██████╔╝██████╔╝██████╔╝
# ╚═════╝ ╚═════╝ ╚═════╝ ╚ ╚═════╝
# ╚═════╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚═════╝

# === general configuration ===
NAME = cub3D
Expand All @@ -27,6 +27,12 @@ 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/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 \
Expand All @@ -35,6 +41,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
Expand Down
85 changes: 71 additions & 14 deletions includes/cub3d.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
# include <X11/keysym.h>
# include <math.h>
# include <stdio.h>
# include <stdbool.h>

/* =========================== */
/* DEFINE */
Expand All @@ -36,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 */
Expand All @@ -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;
Expand Down Expand Up @@ -87,6 +99,10 @@ 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
// === Mouse ===
Copy link

Copilot AI Dec 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Inconsistent indentation: the "// === Mouse ===" comment is indented with a tab character while other similar section comments (like "// === MLX ===" and "// === Game state ===") appear to start at the same indentation level. This should be aligned consistently with the other section comments.

Suggested change
// === Mouse ===
// === Mouse ===

Copilot uses AI. Check for mistakes.
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

-_-

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 */
Expand All @@ -99,50 +115,91 @@ typedef struct s_orientation
double plane_y;
} t_orientation;

/* key binding struct for mapping keys to actions */
typedef struct s_key_binding
{
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;

/* =========================== */
/* EVENT */
/* =========================== */

/* cleanup_exit.c */
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);
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);

/* 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 */
/* =========================== */

/* 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);

/* utils/print_errors.c */
void print_errors(char *p1, char *p2, char *p3);
void print_errors(char *p1, char *p2, char *p3);

#endif
Empty file removed src/events/.gitkeep
Empty file.
27 changes: 27 additions & 0 deletions src/events/cleanup_exit.c
Original file line number Diff line number Diff line change
@@ -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
*/
Comment on lines +3 to +10
Copy link

Copilot AI Dec 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Documentation formatting: The closing part of the docstring has inconsistent indentation. It should be aligned with the opening /** for consistency with the other docstrings in this file.

Copilot uses AI. Check for mistakes.
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot open a new pull request to apply changes based on this feedback

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);
}
Comment on lines +11 to +27
Copy link

Copilot AI Dec 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The cleanup_exit function lacks test coverage. Given that the repository has unit tests for other functionality (see tests/unit/), this critical cleanup function should have tests to verify proper resource deallocation and exit behavior under different scenarios (e.g., when some resources are NULL, when all resources are allocated).

Copilot uses AI. Check for mistakes.
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the test is the program

132 changes: 132 additions & 0 deletions src/events/events_handler.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
#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;
const t_key_binding *bindings;
int i;

game = (t_game *)param;
if (keycode == XK_Escape)
cleanup_exit(game);
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_key_binding *bindings;
int i;

game = (t_game *)param;
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);
}

/**
* @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);
}

/**
* @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_key_binding *bindings;
int i;

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);
}
18 changes: 18 additions & 0 deletions src/events/hooks.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#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);
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);
}
Loading