diff --git a/.vscode/settings.json b/.vscode/settings.json index 62a4eeb..cb9e377 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -13,7 +13,9 @@ "mlx42_int.h": "c", "glad.h": "c", "game_menu.h": "c", - "game_manager.h": "c" + "game_manager.h": "c", + "collision.h": "c", + "monster.h": "c" }, "cmake.ignoreCMakeListsMissing": true } \ No newline at end of file diff --git a/Makefile b/Makefile index b56e7d6..3a43709 100644 --- a/Makefile +++ b/Makefile @@ -1,12 +1,12 @@ # **************************************************************************** # # # -# :::::::: # -# Makefile :+: :+: # -# +:+ # -# By: whaffman +#+ # -# +#+ # -# Created: 2024/10/15 11:48:46 by whaffman #+# #+# # -# Updated: 2025/05/29 12:58:16 by whaffman ######## odam.nl # +# ::: :::::::: # +# Makefile :+: :+: :+: # +# +:+ +:+ +:+ # +# By: qmennen +#+ +:+ +#+ # +# +#+#+#+#+#+ +#+ # +# Created: 2024/10/15 11:48:46 by whaffman #+# #+# # +# Updated: 2025/06/03 21:48:38 by qmennen ### ########.fr # # # # **************************************************************************** # @@ -47,10 +47,10 @@ SOURCES = $(shell basename -a $(shell find $(SRC_PATH) -type f -name "*.c")) # Build configurations BUILD_CONFIGS = release debug asan tsan -release_CFLAGS = -Wall -Werror -Werror -flto -Ofast -march=native -mtune=native -ffast-math +release_CFLAGS = -Wall -Werror -Werror -flto -Ofast -march=native -mtune=native -ffast-math -DFULLSCREEN=0 unity_CFLAGS = -Wall -Werror -Werror -Ofast -march=native -mtune=native -ffast-math debug_CFLAGS = -Wall -Werror -Werror -g3 -DDEBUG -DDBG='fprintf(stderr, RED "DEBUG: " RESET "%s:%d (%s)\n", __FILE__, __LINE__, __PRETTY_FUNCTION__);' -asan_CFLAGS = -Wall -Werror -Werror -flto -fsanitize=address,leak,undefined -g3 +asan_CFLAGS = -Wall -Werror -Werror -flto -fsanitize=address,leak,undefined -g3 -DFULLSCREEN=0 tsan_CFLAGS = -Wall -Werror -Werror -fsanitize=thread -g3 RUN_ARGS=test.cub diff --git a/assets/end_screen.png b/assets/end_screen.png new file mode 100644 index 0000000..7fab44e Binary files /dev/null and b/assets/end_screen.png differ diff --git a/assets/end_screen.xcf b/assets/end_screen.xcf new file mode 100644 index 0000000..06a5b4d Binary files /dev/null and b/assets/end_screen.xcf differ diff --git a/assets/shaders/frag.glsl b/assets/shaders/frag.glsl index 57d9f32..1c8348a 100644 --- a/assets/shaders/frag.glsl +++ b/assets/shaders/frag.glsl @@ -25,6 +25,7 @@ uniform float u_time; uniform float u_battery; uniform vec2 u_resolution; uniform float u_hit_timer; +uniform int u_enabled; float rand(vec2 co) { return fract(sin(dot(co.xy, vec2(12.9898,78.233))) * 43758.5453); @@ -60,6 +61,10 @@ void main() case 15: texColor = texture(Texture15, TexCoord); break; default: texColor = vec4(1.0, 0.0, 0.0, 1.0); break; } + if (u_enabled == 0) { + FragColor = texColor; + return; + } if (TexIndex == 1) { vec2 uv = gl_FragCoord.xy / u_resolution.xy; uv.x *= u_resolution.x / u_resolution.y; diff --git a/assets/surveillor_background.png b/assets/surveillor_background.png new file mode 100644 index 0000000..4275356 Binary files /dev/null and b/assets/surveillor_background.png differ diff --git a/assets/surveillor_background.xcf b/assets/surveillor_background.xcf new file mode 100644 index 0000000..411c9c1 Binary files /dev/null and b/assets/surveillor_background.xcf differ diff --git a/inc/collision.h b/inc/collision.h index a7ab578..3f0b4dc 100644 --- a/inc/collision.h +++ b/inc/collision.h @@ -1,12 +1,12 @@ /* ************************************************************************** */ /* */ -/* :::::::: */ -/* collision.h :+: :+: */ -/* +:+ */ -/* By: qmennen +#+ */ -/* +#+ */ -/* Created: 2025/04/22 14:40:47 by qmennen #+# #+# */ -/* Updated: 2025/05/23 15:11:20 by whaffman ######## odam.nl */ +/* ::: :::::::: */ +/* collision.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: qmennen +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/04/22 14:40:47 by qmennen #+# #+# */ +/* Updated: 2025/06/03 21:24:43 by qmennen ### ########.fr */ /* */ /* ************************************************************************** */ @@ -17,7 +17,7 @@ int collision_horizontal(t_map *map, t_player *player, double xa); int collision_vertical(t_map *map, t_player *player, double ya); -int collision_sprite(t_map *map, t_player *player, double xa, double ya); +int collision_sprite(t_game *game, double xa, double ya); void collect(t_player *player); #endif diff --git a/inc/cub3d.h b/inc/cub3d.h index f871021..7a21f56 100644 --- a/inc/cub3d.h +++ b/inc/cub3d.h @@ -6,7 +6,7 @@ /* By: qmennen +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/15 12:22:29 by qmennen #+# #+# */ -/* Updated: 2025/06/03 15:50:37 by qmennen ### ########.fr */ +/* Updated: 2025/06/03 22:09:53 by qmennen ### ########.fr */ /* */ /* ************************************************************************** */ @@ -20,6 +20,10 @@ # define HEIGHT 1080 # define TITLE "Cub3D" +#ifndef FULLSCREEN +# define FULLSCREEN 1 +#endif + # ifndef M_PI # define M_PI 3.14159265358979323846 # endif @@ -34,6 +38,7 @@ # define CYAN "\033[0;36m" # define WHITE "\033[0;37m" +# define MAX_SCREENSHOTS 3 # define NUM_KEYS 300 # define TILE_SIZE 8 # define MINIMAP_SIZE 300 @@ -61,8 +66,11 @@ # include "game_menu.h" # include "monster.h" -int initialize_cub3d(t_game **game, const char *mapfile); -int shader_init(t_game **game); -void set_uniforms(t_game *game); +int initialize_cub3d(t_game **game, const char *mapfile); +int shader_init(t_game **game); +void set_uniforms(t_game *game); +int load_uniforms(t_game **game); +void count_scores(t_game *game); +int count_tiles(t_map *map, t_tile tile_type); #endif diff --git a/inc/game.h b/inc/game.h index ea3d605..d05d24f 100644 --- a/inc/game.h +++ b/inc/game.h @@ -6,7 +6,7 @@ /* By: qmennen +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/15 15:46:16 by qmennen #+# #+# */ -/* Updated: 2025/05/28 14:28:02 by qmennen ### ########.fr */ +/* Updated: 2025/06/03 15:54:12 by qmennen ### ########.fr */ /* */ /* ************************************************************************** */ @@ -24,5 +24,6 @@ void print_scores(t_game *game); void game_run(t_game *game); void handle_battery(t_game *game); void handle_record(t_game *game); +void handle_flash(t_sprite *sprite, t_game *game); #endif diff --git a/inc/game_menu.h b/inc/game_menu.h index b769198..dc5b99e 100644 --- a/inc/game_menu.h +++ b/inc/game_menu.h @@ -6,7 +6,7 @@ /* By: qmennen +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/05/27 15:07:48 by qmennen #+# #+# */ -/* Updated: 2025/05/28 14:53:54 by qmennen ### ########.fr */ +/* Updated: 2025/06/03 19:15:44 by qmennen ### ########.fr */ /* */ /* ************************************************************************** */ @@ -16,6 +16,8 @@ # include "cub3d.h" void menu_display(t_menu *menu, t_screen *screen); +void draw_end_screen(t_game_manager *manager, t_menu *menu); +t_menu *create_end_screen(t_game_manager *manager); mlx_image_t *menu_load_background(mlx_t *mlx, char *background_path); t_menu *create_main_menu(t_game_manager *manager); t_menu *menu_create(t_game_manager *manager, char *b_path, diff --git a/inc/screen.h b/inc/screen.h index ccfb2d3..4b18818 100644 --- a/inc/screen.h +++ b/inc/screen.h @@ -1,12 +1,12 @@ /* ************************************************************************** */ /* */ -/* :::::::: */ -/* screen.h :+: :+: */ -/* +:+ */ -/* By: qmennen +#+ */ -/* +#+ */ -/* Created: 2025/04/15 15:30:34 by qmennen #+# #+# */ -/* Updated: 2025/05/14 12:43:47 by whaffman ######## odam.nl */ +/* ::: :::::::: */ +/* screen.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: qmennen +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/04/15 15:30:34 by qmennen #+# #+# */ +/* Updated: 2025/06/03 19:44:17 by qmennen ### ########.fr */ /* */ /* ************************************************************************** */ @@ -17,5 +17,6 @@ int screen_create(t_game **game); int screen_display(t_screen *screen); +void fill_background(mlx_image_t *image, int color); #endif diff --git a/inc/types.h b/inc/types.h index a07e703..a8f474d 100644 --- a/inc/types.h +++ b/inc/types.h @@ -6,7 +6,7 @@ /* By: qmennen +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/15 15:52:44 by qmennen #+# #+# */ -/* Updated: 2025/06/03 14:41:00 by qmennen ### ########.fr */ +/* Updated: 2025/06/03 21:55:47 by qmennen ### ########.fr */ /* */ /* ************************************************************************** */ @@ -120,6 +120,11 @@ typedef struct s_screen mlx_image_t *hud; unsigned int width; unsigned int height; + int u_time_location; + int u_battery_location; + int u_resolution_location; + int u_hit_timer_location; + int u_enabled_location; int flash; } t_screen; @@ -135,6 +140,7 @@ typedef enum e_game_state { GAME_STATE_MENU, GAME_STATE_PLAYING, + GAME_STATE_END_SCREEN, } t_game_state; typedef struct s_render @@ -151,16 +157,29 @@ typedef struct s_sprite_column int x; } t_sprite_column; +typedef struct s_scoreboard +{ + int tiles_visited; + int total_tiles; + int collectibles; + int enemies; + mlx_image_t *tiles_text; + mlx_image_t *collectibles_text; + mlx_image_t *battery_text; + mlx_image_t *enemies_text; +} t_scoreboard; typedef struct s_game { - t_map *map; - t_player *player; - t_screen *screen; - t_keyboard *keyboard; - - double elapsed_time; - int fps; + t_map *map; + t_player *player; + t_screen *screen; + t_keyboard *keyboard; + t_scoreboard *scoreboard; + mlx_image_t *screenshots[MAX_SCREENSHOTS]; + struct s_game_manager *manager; + int fps; + int screenshot_idx; } t_game; typedef struct s_game_manager @@ -185,8 +204,6 @@ typedef struct s_menu int num_options; int hidden; t_menu_item *items[MAX_MENU_OPTIONS]; - // char *options[MAX_MENU_OPTIONS]; - // mlx_image_t *option_images[MAX_MENU_OPTIONS]; mlx_image_t *selector; mlx_image_t *background; diff --git a/src/collision.c b/src/game/collision.c similarity index 87% rename from src/collision.c rename to src/game/collision.c index 4dfd304..07563c5 100644 --- a/src/collision.c +++ b/src/game/collision.c @@ -6,7 +6,7 @@ /* By: qmennen +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/22 14:40:59 by qmennen #+# #+# */ -/* Updated: 2025/06/03 15:18:54 by qmennen ### ########.fr */ +/* Updated: 2025/06/03 22:12:38 by qmennen ### ########.fr */ /* */ /* ************************************************************************** */ @@ -19,11 +19,15 @@ void collect(t_player *player) player->battery = 1.f; } -int collision_sprite(t_map *map, t_player *player, double xa, double ya) +int collision_sprite(t_game *game, double xa, double ya) { + t_player *player; + t_map *map; t_sprite *sprites; int i; + player = game->player; + map = game->map; sprites = map->sprites; i = 0; while (i < map->n_sprites) @@ -35,13 +39,14 @@ int collision_sprite(t_map *map, t_player *player, double xa, double ya) { if (sprites[i].type == SPRITE_TYPE_ENEMY) { - player->battery -= 0.0001; + player->battery -= 0.001; player->hit_timer = .65f; } else { sprites[i].type = SPRITE_TYPE_COLLECTED; collect(player); + game->scoreboard->collectibles++; } return (1); } diff --git a/src/game/flash.c b/src/game/flash.c new file mode 100644 index 0000000..02641bc --- /dev/null +++ b/src/game/flash.c @@ -0,0 +1,23 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* flash.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: qmennen +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/06/03 15:53:32 by qmennen #+# #+# */ +/* Updated: 2025/06/03 22:18:26 by qmennen ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "game.h" + +void handle_flash(t_sprite *sprite, t_game *game) +{ + if (sprite->type == SPRITE_TYPE_ENEMY && game->screen->flash == 1 + && sprite->dist < 2.0) + { + sprite->type = SPRITE_TYPE_DISABLED; + game->scoreboard->enemies++; + } +} \ No newline at end of file diff --git a/src/game/game.c b/src/game/game.c index e945234..241f38a 100644 --- a/src/game/game.c +++ b/src/game/game.c @@ -6,7 +6,7 @@ /* By: qmennen +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/15 15:46:08 by qmennen #+# #+# */ -/* Updated: 2025/06/03 14:16:16 by qmennen ### ########.fr */ +/* Updated: 2025/06/03 22:09:28 by qmennen ### ########.fr */ /* */ /* ************************************************************************** */ @@ -19,28 +19,31 @@ int game_create(t_game **game) return (FAILURE); ft_memset(*game, 0, sizeof(t_game)); (*game)->fps = 20; - return (SUCCESS); + (*game)->scoreboard = malloc(sizeof(t_scoreboard)); + if (!(*game)->scoreboard) + { + return (free(*game), FAILURE); + } + return (SUCCESS); } -void free_game(t_game **game) +void game_over(t_game_manager *manager) { - if (game && *game) - { - if ((*game)->screen) - free((*game)->screen); - if ((*game)->player) - free((*game)->player); - if ((*game)->map) - free((*game)->map); - free(*game); - } + t_game *game; + + game = manager->game; + game->screen->hud->instances[0].enabled = false; + game->screen->minimap->instances[0].enabled = false; + game->screen->img->instances[0].enabled = false; + manager->state = GAME_STATE_END_SCREEN; + manager->active_menu = &manager->end_screen; + set_uniforms(game); } void game_run(t_game *game) { static int fps = 0; - game->elapsed_time += game->screen->mlx->delta_time; fps += (int)(1.f / game->screen->mlx->delta_time); set_uniforms(game); player_update(game, game->screen->mlx->delta_time); @@ -49,12 +52,15 @@ void game_run(t_game *game) render_map(game); if (game->player->is_moving) { - game->screen->img->instances[0].x = sin(game->elapsed_time * 10) * 20; - game->screen->img->instances[0].y = cos(game->elapsed_time * 18) * 10; + game->screen->img->instances[0].x = sin(mlx_get_time() * 10) * 20; + game->screen->img->instances[0].y = cos(mlx_get_time() * 18) * 10; } handle_battery(game); handle_record(game); - collision_sprite(game->map, game->player, 0, 0); + collision_sprite(game, 0, 0); + if (game->player->battery <= 0 || count_tiles(game->map, TILE_EMPTY) == 0) + game_over(game->manager); + } void game_free(t_game *game) @@ -67,9 +73,6 @@ void game_free(t_game *game) game->screen->hud = NULL; } mlx_delete_image(game->screen->mlx, game->screen->img); - mlx_close_window(game->screen->mlx); - mlx_terminate(game->screen->mlx); - free(game->screen); } if (game->player) free(game->player); @@ -77,7 +80,6 @@ void game_free(t_game *game) map_free(game->map); if (game->keyboard) free(game->keyboard); - free(game); } void game_terminate(t_game *game) diff --git a/src/game/game_hud.c b/src/game/game_hud.c index 4f23d03..3969897 100644 --- a/src/game/game_hud.c +++ b/src/game/game_hud.c @@ -1,12 +1,12 @@ /* ************************************************************************** */ /* */ -/* :::::::: */ -/* game_hud.c :+: :+: */ -/* +:+ */ -/* By: qmennen +#+ */ -/* +#+ */ -/* Created: 2025/05/28 14:26:29 by qmennen #+# #+# */ -/* Updated: 2025/05/29 11:07:12 by whaffman ######## odam.nl */ +/* ::: :::::::: */ +/* game_hud.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: qmennen +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/05/28 14:26:29 by qmennen #+# #+# */ +/* Updated: 2025/06/03 19:22:47 by qmennen ### ########.fr */ /* */ /* ************************************************************************** */ @@ -57,7 +57,8 @@ void handle_battery(t_game *game) if (game->player->battery < 0) { game->player->battery = 0; - game_terminate(game); + game->manager->state = GAME_STATE_MENU; + // game_terminate(game); } draw_battery(game->screen->minimap, game->player->battery); } @@ -68,7 +69,7 @@ void handle_record(t_game *game) int x; int y; - flash = ((int) game->elapsed_time) % 2; + flash = (int) mlx_get_time() % 2; y = -15; while (y <= 15) { diff --git a/src/moves.c b/src/game/moves.c similarity index 97% rename from src/moves.c rename to src/game/moves.c index e62c000..d2cff06 100644 --- a/src/moves.c +++ b/src/game/moves.c @@ -6,7 +6,7 @@ /* By: qmennen +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/05/14 20:08:27 by whaffman #+# #+# */ -/* Updated: 2025/06/03 15:10:49 by qmennen ### ########.fr */ +/* Updated: 2025/06/03 22:13:43 by qmennen ### ########.fr */ /* */ /* ************************************************************************** */ diff --git a/src/player.c b/src/game/player.c similarity index 100% rename from src/player.c rename to src/game/player.c diff --git a/src/main.c b/src/main.c index 648548b..65c3155 100644 --- a/src/main.c +++ b/src/main.c @@ -1,12 +1,12 @@ /* ************************************************************************** */ /* */ -/* :::::::: */ -/* main.c :+: :+: */ -/* +:+ */ -/* By: whaffman +#+ */ -/* +#+ */ -/* Created: 2025/04/15 16:01:29 by qmennen #+# #+# */ -/* Updated: 2025/06/03 13:43:05 by whaffman ######## odam.nl */ +/* ::: :::::::: */ +/* main.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: qmennen +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/04/15 16:01:29 by qmennen #+# #+# */ +/* Updated: 2025/06/03 19:30:56 by qmennen ### ########.fr */ /* */ /* ************************************************************************** */ @@ -21,7 +21,6 @@ int main(int argc, char **argv) game = NULL; if (!valid_arguments(argc, argv)) return (EXIT_FAILURE); - shader_init(&game); if (!initialize_cub3d(&game, argv[1])) { perror("initialize_cub3d"); @@ -30,8 +29,9 @@ int main(int argc, char **argv) } manager = game_manager_create(game); manager->menu = create_main_menu(manager); + manager->end_screen = create_end_screen(manager); manager->active_menu = &manager->menu; - mlx_key_hook(game->screen->mlx, keyhandle, game); + mlx_key_hook(game->screen->mlx, keyhandle, manager); mlx_loop_hook(game->screen->mlx, game_manager_update, manager); mlx_loop(game->screen->mlx); game_manager_destroy(manager); diff --git a/src/manager/game_manager.c b/src/manager/game_manager.c index f179aac..32324c2 100644 --- a/src/manager/game_manager.c +++ b/src/manager/game_manager.c @@ -6,7 +6,7 @@ /* By: qmennen +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/05/27 13:48:18 by qmennen #+# #+# */ -/* Updated: 2025/06/03 14:55:46 by qmennen ### ########.fr */ +/* Updated: 2025/06/03 20:49:50 by qmennen ### ########.fr */ /* */ /* ************************************************************************** */ @@ -22,6 +22,7 @@ t_game_manager *game_manager_create(t_game *game) manager->game = game; manager->menu = NULL; manager->state = GAME_STATE_MENU; + game->manager = manager; return (manager); } @@ -36,6 +37,8 @@ void game_manager_display(t_game_manager *manager) menu_display(*(manager->active_menu), game->screen); else if (manager->state == GAME_STATE_PLAYING) game_run(game); + else if (manager->state == GAME_STATE_END_SCREEN) + draw_end_screen(manager, manager->end_screen); } void game_manager_update(void *param) @@ -58,9 +61,11 @@ void game_manager_destroy(t_game_manager *manager) menu_free(manager->end_screen, manager->game->screen); print_scores(manager->game); if (manager->game) - { game_free(manager->game); - } + mlx_close_window(manager->game->screen->mlx); + mlx_terminate(manager->game->screen->mlx); + free(manager->game->screen); + free(manager->game); free(manager); exit(EXIT_SUCCESS); } diff --git a/src/manager/game_manager_utils.c b/src/manager/game_manager_utils.c index 5b4b3d6..9f9de2e 100644 --- a/src/manager/game_manager_utils.c +++ b/src/manager/game_manager_utils.c @@ -6,7 +6,7 @@ /* By: qmennen +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/05/27 15:22:15 by qmennen #+# #+# */ -/* Updated: 2025/05/28 15:03:04 by qmennen ### ########.fr */ +/* Updated: 2025/06/03 20:35:05 by qmennen ### ########.fr */ /* */ /* ************************************************************************** */ @@ -38,7 +38,7 @@ void game_manager_handle_input(t_game_manager *manager) if (get_key_up(manager->game, MLX_KEY_UP)) { (*manager->active_menu)->selected_option--; - if (manager->menu->selected_option < 0) - manager->menu->selected_option = manager->menu->num_options - 1; + if ((*manager->active_menu)->selected_option < 0) + (*manager->active_menu)->selected_option = (*manager->active_menu)->num_options - 1; } } diff --git a/src/menu/end_screen.c b/src/menu/end_screen.c new file mode 100644 index 0000000..de0a729 --- /dev/null +++ b/src/menu/end_screen.c @@ -0,0 +1,120 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* end_screen.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: qmennen +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/06/03 16:20:35 by qmennen #+# #+# */ +/* Updated: 2025/06/03 22:07:06 by qmennen ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "game_menu.h" + +static void slideshow(t_game *game) +{ + static int frame_idx = 0; + static int last_frame_time; + + if (game->screenshots[frame_idx]) + game->screenshots[frame_idx]->instances[0].enabled = true; + if (last_frame_time == 0) + last_frame_time = mlx_get_time(); + if (mlx_get_time() - last_frame_time > 5 && frame_idx < game->screenshot_idx && frame_idx < MAX_SCREENSHOTS) { + game->screenshots[frame_idx++]->instances[0].enabled = true; + game->screenshots[frame_idx - 1]->instances[0].enabled = false; + last_frame_time = mlx_get_time(); + frame_idx %= (MAX_SCREENSHOTS < game->screenshot_idx) * MAX_SCREENSHOTS + (MAX_SCREENSHOTS >= game->screenshot_idx) * game->screenshot_idx; + } +} + +char *get_score_text(char *prefix, char *suffix, int score) +{ + char *score_text; + char *score_complete; + char *score_value; + + score_text = ft_itoa(score); + if (!score_text) + return (NULL); + score_value = ft_strjoin(prefix, score_text); + free(score_text); + if (!score_value) + return (NULL); + if (!suffix) + return (score_value); + score_complete = ft_strjoin(score_value, suffix); + free(score_value); + return (score_complete); +} + +static mlx_image_t *draw_score_line(mlx_t *mlx, char *text, int x, int y) +{ + mlx_image_t *image; + + if (!text) + return (NULL); + image = mlx_put_string(mlx, text, x, y); + free(text); + return (image); +} + +void draw_end_screen(t_game_manager *manager, t_menu *menu) +{ + char *tiles_score; + char *battery_percentage; + char *collectibles_score; + char *enemies_score; + t_game *game; + + if (!manager || !manager->game) + return ; + game = manager->game; + slideshow(game); + if (menu->hidden) + { + menu_toggle(menu, game->screen); + count_scores(game); + } + menu->selector->instances[0].y = manager->game->screen->height / 2 + + menu->selected_option * 50; + tiles_score = get_score_text("Discovered area: ", "%", + (double) game->scoreboard->tiles_visited / game->scoreboard->total_tiles * 100); + game->scoreboard->tiles_text = draw_score_line(game->screen->mlx, + tiles_score, 100, game->screen->height / 2 - 50); + battery_percentage = get_score_text("Battery percentage: ", + "%", (double) game->player->battery * 100); + game->scoreboard->battery_text = draw_score_line(game->screen->mlx, + battery_percentage, 100, game->screen->height / 2); + collectibles_score = get_score_text("Batteries found: ", NULL, + game->scoreboard->collectibles); + game->scoreboard->collectibles_text = draw_score_line(game->screen->mlx, + collectibles_score, 100, game->screen->height / 2 + 50); + enemies_score = get_score_text("Enemies defeated: ", NULL, + game->scoreboard->enemies); + game->scoreboard->enemies_text = draw_score_line(game->screen->mlx, + enemies_score, 100, game->screen->height / 2 + 100); +} + +static void game_exit(struct s_menu_item *item, t_game_manager *manager) +{ + (void)item; + game_manager_destroy(manager); +} + +t_menu *create_end_screen(t_game_manager *manager) +{ + const t_menu_item *menu_items[] = { + menu_item_create(manager->game->screen, "Room discovery: ", game_exit), + NULL + }; + t_menu *menu; + + menu = menu_create(manager, "assets/end_screen.png", menu_items); + menu->items[0]->image->instances[0].x = 100; + menu->items[0]->image->instances[0].y = manager->game->screen->height / 2; + if (!menu) + return (NULL); + return (menu); +} diff --git a/src/menu/main_menu.c b/src/menu/main_menu.c index a96c52e..06cd7aa 100644 --- a/src/menu/main_menu.c +++ b/src/menu/main_menu.c @@ -6,7 +6,7 @@ /* By: qmennen +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/05/28 14:14:11 by qmennen #+# #+# */ -/* Updated: 2025/06/03 14:19:45 by qmennen ### ########.fr */ +/* Updated: 2025/06/03 20:15:01 by qmennen ### ########.fr */ /* */ /* ************************************************************************** */ @@ -26,16 +26,8 @@ static void game_start(struct s_menu_item *item, t_game_manager *manager) (void)item; game = manager->game; screen = game->screen; - if (mlx_image_to_window(screen->mlx, screen->minimap, 175, 575) < 0) - { - printf(RED "Failed to display buffer image\n" RESET); - game_terminate(game); - } - if (mlx_image_to_window(screen->mlx, screen->hud, 0, 0) < 0) - { - printf(RED "Failed to display buffer image\n" RESET); - game_terminate(game); - } + game->screen->minimap->instances[0].enabled = true; + game->screen->hud->instances[0].enabled = true; menu_toggle(*(manager->active_menu), screen); manager->state = GAME_STATE_PLAYING; } @@ -50,7 +42,7 @@ t_menu *create_main_menu(t_game_manager *manager) }; t_menu *menu; - menu = menu_create(manager, "./assets/menu_background.png", menu_items); + menu = menu_create(manager, "./assets/surveillor_background.png", menu_items); if (!menu) return (NULL); return (menu); diff --git a/src/menu/menu.c b/src/menu/menu.c index c31d8c6..e59e75b 100644 --- a/src/menu/menu.c +++ b/src/menu/menu.c @@ -6,7 +6,7 @@ /* By: qmennen +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/05/27 14:31:53 by qmennen #+# #+# */ -/* Updated: 2025/06/03 14:22:52 by qmennen ### ########.fr */ +/* Updated: 2025/06/03 20:16:52 by qmennen ### ########.fr */ /* */ /* ************************************************************************** */ @@ -25,13 +25,14 @@ t_menu *menu_create(t_game_manager *manager, char *b_path, if (b_path) menu->background = menu_load_background( manager->game->screen->mlx, b_path); - if (mlx_image_to_window( + if (b_path && mlx_image_to_window( manager->game->screen->mlx, menu->background, 0, 0) < 0) { mlx_delete_image(manager->game->screen->mlx, menu->background); return (free(menu), NULL); } - menu->background->instances[0].enabled = false; + if (menu->background) + menu->background->instances[0].enabled = false; menu->hidden = 1; i = -1; while (options[++i]) @@ -52,13 +53,12 @@ void menu_display(t_menu *menu, t_screen *screen) half_h = screen->height / 2; if (menu->hidden) menu_toggle(menu, screen); - menu->selector->instances[0].x = half_w - 100; + menu->selector->instances[0].x = 150; menu->selector->instances[0].y = half_h + menu->selected_option * 50; i = 0; while (i < menu->num_options) { - menu->items[i]->image->instances[0].x = (screen->width - - ft_strlen(menu->items[i]->text) * 10) / 2; + menu->items[i]->image->instances[0].x = 200; menu->items[i]->image->instances[0].y = half_h + i * 50; i++; } @@ -93,9 +93,8 @@ void menu_free(t_menu *menu, t_screen *screen) while (i < menu->num_options) { if (menu->items[i]->image) - { mlx_delete_image(screen->mlx, menu->items[i]->image); - } + free(menu->items[i]); i++; } if (menu->selector) diff --git a/src/menu/menu_item.c b/src/menu/menu_item.c index cae2fb4..3a78f32 100644 --- a/src/menu/menu_item.c +++ b/src/menu/menu_item.c @@ -6,7 +6,7 @@ /* By: qmennen +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/05/28 13:50:14 by qmennen #+# #+# */ -/* Updated: 2025/05/28 15:12:45 by qmennen ### ########.fr */ +/* Updated: 2025/06/03 16:23:36 by qmennen ### ########.fr */ /* */ /* ************************************************************************** */ @@ -24,6 +24,7 @@ t_menu_item *menu_item_create(t_screen *screen, const char *text, item->text = (char *)text; item->act = act; item->image = mlx_put_string(screen->mlx, text, 0, 0); + // mlx_resize_image(item->image, 200, 50); item->image->instances[0].enabled = false; return (item); } diff --git a/src/parser/parse_config_line.c b/src/parser/parse_config_line.c index 2f519d8..0b77ec3 100644 --- a/src/parser/parse_config_line.c +++ b/src/parser/parse_config_line.c @@ -1,12 +1,12 @@ /* ************************************************************************** */ /* */ -/* :::::::: */ -/* parse_config_line.c :+: :+: */ -/* +:+ */ -/* By: whaffman +#+ */ -/* +#+ */ -/* Created: 2025/04/22 13:10:06 by whaffman #+# #+# */ -/* Updated: 2025/06/03 14:40:15 by whaffman ######## odam.nl */ +/* ::: :::::::: */ +/* parse_config_line.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: qmennen +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/04/22 13:10:06 by whaffman #+# #+# */ +/* Updated: 2025/06/03 16:16:56 by qmennen ### ########.fr */ /* */ /* ************************************************************************** */ @@ -16,7 +16,7 @@ mlx_texture_t *load_texture(const char *path) { mlx_texture_t *texture; - printf("Loading texture: |%s|\n", path); + // printf("Loading texture: |%s|\n", path); texture = mlx_load_png(path); if (texture == NULL) { @@ -39,7 +39,7 @@ t_token_handler handle_config_token(const char *token, t_map *map) int i; i = 0; - printf("Token: %s\n", token); + // printf("Token: %s\n", token); while (config_tokens[i] != NULL) { if (ft_strcmp(token, config_tokens[i]) == 0) diff --git a/src/render/render.c b/src/render/render.c index 8286e93..4779ff9 100644 --- a/src/render/render.c +++ b/src/render/render.c @@ -1,17 +1,54 @@ /* ************************************************************************** */ /* */ -/* :::::::: */ -/* render.c :+: :+: */ -/* +:+ */ -/* By: whaffman +#+ */ -/* +#+ */ -/* Created: 2025/04/15 16:28:10 by qmennen #+# #+# */ -/* Updated: 2025/06/03 13:38:16 by whaffman ######## odam.nl */ +/* ::: :::::::: */ +/* render.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: qmennen +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/04/15 16:28:10 by qmennen #+# #+# */ +/* Updated: 2025/06/03 22:17:23 by qmennen ### ########.fr */ /* */ /* ************************************************************************** */ #include "cub3d.h" +void create_screenshot(t_game *game) +{ + int i; + int j; + int idx1; + int idx2; + mlx_image_t *screenshot; + if (!game->screenshots[game->screenshot_idx % MAX_SCREENSHOTS]) + { + game->screenshots[game->screenshot_idx % MAX_SCREENSHOTS] = mlx_new_image(game->screen->mlx, game->screen->width / 3, game->screen->height / 3); + mlx_image_to_window(game->screen->mlx, game->screenshots[game->screenshot_idx % MAX_SCREENSHOTS], 1000, 250); + game->screenshots[game->screenshot_idx % MAX_SCREENSHOTS]->instances[0].enabled = false; + } + screenshot = game->screenshots[game->screenshot_idx % MAX_SCREENSHOTS]; + if (!screenshot) + return ; + i = 0; + while (i < game->screen->height / 3) + { + j = 0; + while (j < game->screen->width / 3) + { + idx1 = (i * game->screen->width / 3 + j) * 4; + idx2 = (i * game->screen->img->width + j) * 12; + screenshot->pixels[idx1] = game->screen->img->pixels[idx2]; + screenshot->pixels[idx1 + 1] = game->screen->img->pixels[idx2 + 1]; + screenshot->pixels[idx1 + 2] = game->screen->img->pixels[idx2 + 2]; + screenshot->pixels[idx1 + 3] = game->screen->img->pixels[idx2 + 3]; + j++; + } + i++; + } + printf("Screenshot %d taken\n", game->screenshot_idx); + + game->screenshot_idx++; + return ; +} void flash(t_game *game) { mlx_image_t *img; @@ -21,7 +58,8 @@ void flash(t_game *game) if (game->screen->flash == 0) return ; img = game->screen->img; - game->screen->flash--; + if (game->screen->flash == 2) + create_screenshot(game); x = 0; while (x < img->width) { @@ -33,6 +71,7 @@ void flash(t_game *game) } x++; } + game->screen->flash--; } void cast_rays(t_game *game) diff --git a/src/render/render_sprite.c b/src/render/render_sprite.c index 8e84db0..67f3235 100644 --- a/src/render/render_sprite.c +++ b/src/render/render_sprite.c @@ -6,7 +6,7 @@ /* By: qmennen +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/05/08 12:23:17 by qmennen #+# #+# */ -/* Updated: 2025/06/03 15:00:43 by qmennen ### ########.fr */ +/* Updated: 2025/06/03 22:15:19 by qmennen ### ########.fr */ /* */ /* ************************************************************************** */ @@ -48,7 +48,7 @@ static void draw_sprite_column( unsigned int color; int frame; - frame = (game->elapsed_time * sprite->animation_speed); + frame = (mlx_get_time() * sprite->animation_speed); frame %= sprite->n_frames; inv_range.y = 1.0 / (column.end.y - column.start.y); inv_range.x = 1.0 / (column.end.x - column.start.x); @@ -69,13 +69,6 @@ static void draw_sprite_column( } } -void handle_flash(t_sprite *sprite, t_game *game) -{ - if (sprite->type == SPRITE_TYPE_ENEMY && game->screen->flash > 0 - && sprite->dist < 2.0) - sprite->type = SPRITE_TYPE_DISABLED; -} - void draw_sprite(t_game *game, t_sprite *sprite, t_render *render) { t_vec2_int start; diff --git a/src/screen.c b/src/screen.c index ec053aa..2ac2ff3 100644 --- a/src/screen.c +++ b/src/screen.c @@ -6,7 +6,7 @@ /* By: qmennen +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/15 15:30:27 by qmennen #+# #+# */ -/* Updated: 2025/06/03 15:47:36 by qmennen ### ########.fr */ +/* Updated: 2025/06/03 20:20:36 by qmennen ### ########.fr */ /* */ /* ************************************************************************** */ @@ -23,7 +23,7 @@ int screen_create(t_game **game) ft_memset(screen, 0, sizeof(t_screen)); screen->width = WIDTH; screen->height = HEIGHT; - mlx_set_setting(MLX_FULLSCREEN, 1); + mlx_set_setting(MLX_FULLSCREEN, FULLSCREEN); mlx = mlx_init(WIDTH, HEIGHT, TITLE, true); if (!mlx) return (FAILURE); @@ -41,18 +41,18 @@ int screen_create(t_game **game) return (SUCCESS); } -void fill_background(t_screen *screen, int color) +void fill_background(mlx_image_t *image, int color) { int i; int j; i = 0; - while (i < screen->width) + while (i < image->width) { j = 0; - while (j < screen->height) + while (j < image->height) { - mlx_put_pixel(screen->background, i, j, color); + mlx_put_pixel(image, i, j, color); j++; } i++; @@ -68,10 +68,7 @@ int center_window(t_screen *screen) m_height = 0; mlx_get_monitor_size(0, &m_width, &m_height); if (m_width == 0 || m_height == 0) - { - printf(RED"Failed to retrieve monitor size to center window\n"RESET); return (FAILURE); - } mlx_set_window_pos(screen->mlx, (m_width - screen->width) / 2, (m_height - screen->height) / 2); return (SUCCESS); @@ -79,18 +76,21 @@ int center_window(t_screen *screen) int screen_display(t_screen *screen) { - fill_background(screen, 0x000000FF); - if (mlx_image_to_window(screen->mlx, screen->background, 0, 0) < 0) + int display_error; + fill_background(screen->background, 0x000000FF); + + display_error = 0; + display_error |= mlx_image_to_window(screen->mlx, screen->background, 0, 0) < 0; + display_error |= mlx_image_to_window(screen->mlx, screen->img, 0, 0) < 0; + display_error |= mlx_image_to_window(screen->mlx, screen->minimap, 175, 575) < 0; + display_error |= mlx_image_to_window(screen->mlx, screen->hud, 0, 0) < 0; + + if (display_error || !center_window(screen)) { - printf(RED"Failed to display buffer image\n"RESET); + printf(RED "Display failed to initialize\n" RESET); return (FAILURE); } - if (mlx_image_to_window(screen->mlx, screen->img, 0, 0) < 0) - { - printf(RED"Failed to display buffer image\n"RESET); - return (FAILURE); - } - if (!center_window(screen)) - return (FAILURE); + screen->hud->instances[0].enabled = false; + screen->minimap->instances[0].enabled = false; return (SUCCESS); } diff --git a/src/shader/shaders.c b/src/shader/shaders.c index 98d8442..520b3e9 100644 --- a/src/shader/shaders.c +++ b/src/shader/shaders.c @@ -6,7 +6,7 @@ /* By: qmennen +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/05/08 18:27:59 by qmennen #+# #+# */ -/* Updated: 2025/06/03 14:41:38 by qmennen ### ########.fr */ +/* Updated: 2025/06/03 19:34:08 by qmennen ### ########.fr */ /* */ /* ************************************************************************** */ @@ -19,14 +19,32 @@ void set_uniforms(t_game *game) mlx_ctx_t *ctx; ctx = (mlx_ctx_t *)game->screen->mlx->context; - glUniform1f(glGetUniformLocation(ctx->shaderprogram, "u_time"), - glfwGetTime()); - glUniform1f(glGetUniformLocation(ctx->shaderprogram, "u_battery"), - game->player->battery); - glUniform2f(glGetUniformLocation(ctx->shaderprogram, "u_resolution"), - game->screen->width, game->screen->height); - glUniform1f(glGetUniformLocation(ctx->shaderprogram, "u_hit_timer"), - game->player->hit_timer); + glUniform1f(game->screen->u_time_location, (float)mlx_get_time()); + glUniform1f(game->screen->u_battery_location, game->player->battery); + glUniform2f(game->screen->u_resolution_location, + (float)game->screen->width, (float)game->screen->height); + glUniform1f(game->screen->u_hit_timer_location, game->player->hit_timer); + glUniform1i(game->screen->u_enabled_location, + game->manager->state == GAME_STATE_PLAYING); +} + +int load_uniforms(t_game **game) +{ + mlx_ctx_t *ctx; + + ctx = (mlx_ctx_t *)(*game)->screen->mlx->context; + (*game)->screen->u_time_location = glGetUniformLocation(ctx->shaderprogram, "u_time"); + (*game)->screen->u_battery_location = glGetUniformLocation(ctx->shaderprogram, "u_battery"); + (*game)->screen->u_hit_timer_location = glGetUniformLocation(ctx->shaderprogram, "u_hit_timer"); + (*game)->screen->u_enabled_location = glGetUniformLocation(ctx->shaderprogram, "u_enabled"); + (*game)->screen->u_resolution_location = glGetUniformLocation(ctx->shaderprogram, "u_resolution"); + if ((*game)->screen->u_time_location < 0 || + (*game)->screen->u_battery_location < 0 || + (*game)->screen->u_hit_timer_location < 0 || + (*game)->screen->u_enabled_location < 0 || + (*game)->screen->u_resolution_location < 0) + return (FAILURE); + return (SUCCESS); } static const char *read_vertex_shader(void) diff --git a/src/util/hooks.c b/src/util/hooks.c index 92869a6..3ba637d 100644 --- a/src/util/hooks.c +++ b/src/util/hooks.c @@ -6,7 +6,7 @@ /* By: qmennen +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/15 17:51:26 by qmennen #+# #+# */ -/* Updated: 2025/04/17 19:57:35 by qmennen ### ########.fr */ +/* Updated: 2025/06/03 16:11:46 by qmennen ### ########.fr */ /* */ /* ************************************************************************** */ @@ -14,9 +14,9 @@ void keyhandle(mlx_key_data_t keydata, void *param) { - t_game *game; + t_game_manager *manager; - game = (t_game *)param; + manager = (t_game_manager *)param; if (keydata.key == MLX_KEY_ESCAPE) - game_terminate(game); + game_manager_destroy(manager); } diff --git a/src/util/initialize.c b/src/util/initialize.c index f3626ff..801489e 100644 --- a/src/util/initialize.c +++ b/src/util/initialize.c @@ -1,12 +1,12 @@ /* ************************************************************************** */ /* */ -/* :::::::: */ -/* initialize.c :+: :+: */ -/* +:+ */ -/* By: qmennen +#+ */ -/* +#+ */ -/* Created: 2025/04/22 17:08:26 by qmennen #+# #+# */ -/* Updated: 2025/06/03 13:41:33 by whaffman ######## odam.nl */ +/* ::: :::::::: */ +/* initialize.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: qmennen +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/04/22 17:08:26 by qmennen #+# #+# */ +/* Updated: 2025/06/03 19:31:25 by qmennen ### ########.fr */ /* */ /* ************************************************************************** */ @@ -47,8 +47,12 @@ int initialize_cub3d(t_game **game, const char *mapfile) return (FAILURE); if (!texture_load(*game)) return (FAILURE); + if (!shader_init(game)) + return (FAILURE); if (!screen_create(game)) return (FAILURE); + if (!load_uniforms(game)) + return (FAILURE); if (!keyboard_create(game)) return (FAILURE); if (!init_temp(game)) diff --git a/src/util/score.c b/src/util/score.c index 9a4ad57..038f512 100644 --- a/src/util/score.c +++ b/src/util/score.c @@ -6,7 +6,7 @@ /* By: qmennen +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/05/25 20:54:23 by whaffman #+# #+# */ -/* Updated: 2025/05/28 17:14:53 by qmennen ### ########.fr */ +/* Updated: 2025/06/03 21:42:54 by qmennen ### ########.fr */ /* */ /* ************************************************************************** */ @@ -63,3 +63,13 @@ void print_scores(t_game *game) printf("Seen %d of %d tiles\n", visited, visited + empty); printf("Collected items: %d\n", collected); } + +void count_scores(t_game *game) +{ + t_scoreboard *scoreboard; + + scoreboard = game->scoreboard; + scoreboard->tiles_visited = count_tiles(game->map, TILE_VISITED); + scoreboard->total_tiles = count_tiles(game->map, TILE_EMPTY) + scoreboard->tiles_visited; + scoreboard->collectibles = count_collected(game); +}