From a06b7889da184f2ae5f7125ed2f1fea0cb33afff Mon Sep 17 00:00:00 2001 From: Quinten Mennen Date: Thu, 8 May 2025 15:59:54 +0200 Subject: [PATCH] sprites duhhh --- .vscode/settings.json | 3 +- assets/battery.png | Bin 0 -> 6666 bytes inc/render.h | 16 ++-- inc/types.h | 13 +++- src/player.c | 8 +- src/render/DDAscratch.c | 9 ++- src/render/render_sprite.c | 156 +++++++++++++++++++++++++++++++++++++ src/screen.c | 3 +- src/util/initialize.c | 31 ++++++-- 9 files changed, 215 insertions(+), 24 deletions(-) create mode 100644 assets/battery.png create mode 100644 src/render/render_sprite.c diff --git a/.vscode/settings.json b/.vscode/settings.json index 0ff9eaf..660b980 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -7,7 +7,8 @@ "glfw3.h": "c", "vec_math.h": "c", "texture.h": "c", - "libft.h": "c" + "libft.h": "c", + "render.h": "c" }, "cmake.ignoreCMakeListsMissing": true } \ No newline at end of file diff --git a/assets/battery.png b/assets/battery.png new file mode 100644 index 0000000000000000000000000000000000000000..ebc8ad1467680d884a1e085f0479b44825aa342c GIT binary patch literal 6666 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 +#+ */ -/* +#+ */ -/* Created: 2025/04/15 16:28:16 by qmennen #+# #+# */ -/* Updated: 2025/05/04 13:21:04 by whaffman ######## odam.nl */ +/* ::: :::::::: */ +/* render.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: qmennen +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/04/15 16:28:16 by qmennen #+# #+# */ +/* Updated: 2025/05/08 14:50:38 by qmennen ### ########.fr */ /* */ /* ************************************************************************** */ @@ -22,6 +22,6 @@ void render_clear(t_screen *screen); void render_entities(t_game *game); void render_map(t_screen *screen, t_map *map); void cast_rays(t_game *game); - +void render_sprites(t_render* render, t_game *game); #endif diff --git a/inc/types.h b/inc/types.h index 19b93e7..6940a86 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/05/06 20:03:48 by qmennen ### ########.fr */ +/* Updated: 2025/05/08 14:51:17 by qmennen ### ########.fr */ /* */ /* ************************************************************************** */ @@ -52,6 +52,15 @@ typedef struct s_player int is_moving; } t_player; +typedef struct s_sprite +{ + int n_frames; + double dist; + double cam_frac; + mlx_texture_t *texture; + t_vec2 pos; +} t_sprite; + typedef struct s_map { unsigned int width; @@ -64,6 +73,8 @@ typedef struct s_map mlx_texture_t *texture_floor; mlx_texture_t *texture_ceiling; mlx_texture_t *textures[4]; + t_sprite *sprites; + unsigned int n_sprites; unsigned int floor_color; unsigned int ceiling_color; } t_map; diff --git a/src/player.c b/src/player.c index e776425..97652ff 100644 --- a/src/player.c +++ b/src/player.c @@ -6,7 +6,7 @@ /* By: qmennen +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/15 18:53:19 by qmennen #+# #+# */ -/* Updated: 2025/05/06 19:54:42 by qmennen ### ########.fr */ +/* Updated: 2025/05/08 15:51:06 by qmennen ### ########.fr */ /* */ /* ************************************************************************** */ @@ -59,9 +59,15 @@ static void strave(t_map *map, t_player *player, int dir, double delta) xa = dir * perp(player->dir).x * player->speed * delta; ya = dir * perp(player->dir).y * player->speed * delta; if (xa != 0 && collision_horizontal(map, player, xa)) + { player->pos.x += xa; + player->is_moving = 1; + } if (ya != 0 && collision_vertical(map, player, ya)) + { + player->is_moving = 1; player->pos.y += ya; + } } static void rotate(t_player *player, double rot_speed) diff --git a/src/render/DDAscratch.c b/src/render/DDAscratch.c index 0161277..6d16a94 100644 --- a/src/render/DDAscratch.c +++ b/src/render/DDAscratch.c @@ -6,7 +6,7 @@ /* By: qmennen +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/05/02 11:58:09 by whaffman #+# #+# */ -/* Updated: 2025/05/06 19:56:47 by qmennen ### ########.fr */ +/* Updated: 2025/05/08 14:51:32 by qmennen ### ########.fr */ /* */ /* ************************************************************************** */ @@ -224,14 +224,15 @@ void draw_floor(t_game *game) void cast_rays(t_game *game) { int x; - t_render render; + t_render render[WIDTH]; x = 0; draw_floor(game); while (x < game->screen->width) { - render = cast_ray(game, x); - draw_line(game, render, x); + render[x] = cast_ray(game, x); + draw_line(game, render[x], x); x++; } + render_sprites(render, game); } diff --git a/src/render/render_sprite.c b/src/render/render_sprite.c new file mode 100644 index 0000000..d15a84d --- /dev/null +++ b/src/render/render_sprite.c @@ -0,0 +1,156 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* render_sprite.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: qmennen +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/05/08 12:23:17 by qmennen #+# #+# */ +/* Updated: 2025/05/08 15:59:32 by qmennen ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "render.h" + +static void sort_sprites(t_game *game) +{ + t_sprite sprite_temp; + int n; + int i; + int new_n; + + n = game->map->n_sprites; + while (n > 1) + { + i = 1; + new_n = 0; + while (i < n - 1) + { + if (game->map->sprites[i - 1].dist < game->map->sprites[i].dist) + { + sprite_temp = game->map->sprites[i - 1]; + game->map->sprites[i - 1] = game->map->sprites[i]; + game->map->sprites[i] = sprite_temp; + new_n = i; + } + i++; + } + n = new_n; + } +} + +static void calculate_sprite_dist(t_game *game) +{ + int i; + t_vec2 player_pos; + + i = 0; + player_pos = game->player->pos; + while (i < game->map->n_sprites) + { + game->map->sprites[i].dist = dist_point_line(game->map->sprites[i].pos, + (t_vec2_line){player_pos, game->player->camera}); + i++; + } +} + +static void cam_fraction(t_game *game, t_sprite *sprite) +{ + t_vec2 ps; + double frac_cam; + double frac_sprite; + double denominator; + + ps = sub(sprite->pos, game->player->pos); + frac_cam = (ps.y * game->player->dir.x - ps.x * game->player->dir.y); + denominator = (ps.x * game->player->camera.y - ps.y * game->player->camera.x); + frac_sprite = (game->player->camera.y * game->player->dir.x - game->player->camera.x * game->player->dir.y); + if (denominator == 0 || (frac_sprite / denominator) < 0) + { + sprite->cam_frac = NAN; + return; + } + sprite->cam_frac = frac_cam / denominator; + if (sprite->cam_frac < -1 || sprite->cam_frac > 1) + { + sprite->cam_frac = NAN; + return; + } + return; +} + +unsigned int sample_texture_color(mlx_texture_t *texture, int x, int y, double dist) +{ + int index; + int alpha; + + alpha = 1.0 / dist * 255; + index = (x + y * texture->width) * texture->bytes_per_pixel; + if (texture->pixels[index + 3] == 0) + { + alpha = 0; + } + return texture->pixels[index] << 24 | texture->pixels[index + 1] << 16 | texture->pixels[index + 2] << 8 | alpha; +} + +void draw_sprite(t_game *game, t_sprite *sprite) +{ + double sprite_scale; + int x_start; + int y_start; + int x_end; + int y_end; + int x; + int y; + double tex_x; + double tex_y; + unsigned int color; + + if (isnan(sprite->cam_frac) || sprite->dist < 1) + return; + sprite_scale = (1 / sprite->dist) * 16; + printf("scale %f, dist: %f\n", sprite_scale, sprite->dist); + x_start = (game->screen->width / 2) * (1 + sprite->cam_frac) - ((sprite->texture->width * sprite_scale) / 2); + y_start = (game->screen->height / 2) - (sprite->texture->height * sprite_scale) / 2 ; + x_end = (game->screen->width / 2) * (1 + sprite->cam_frac) + ((sprite->texture->width * sprite_scale) / 2); + y_end = (game->screen->height / 2) + (sprite->texture->height * sprite_scale) / 2 ; + x = x_start; + y = y_start; + while (y < y_end) + { + if (y < 0 || y >= game->screen->height) + break; + x = (int)x_start; + while (x < x_end) + { + tex_x = ((double)((x - x_start) / (double)(x_end - x_start))) * sprite->texture->width; + tex_y = ((double)((y- y_start) / (double)(y_end - y_start))) * sprite->texture->height; + // printf("\e[1;1H\e[2J"); + // printf("x: %d, y: %d, tex_x: %d, tex_y: %d\n", x, y, (int) tex_x, (int) tex_y); + color = sample_texture_color(sprite->texture, (int)(tex_x), (int)(tex_y), sprite->dist); + if (x < 0 || x >= game->screen->width || y < 0 || y >= game->screen->height || (color & 0xFF) == 0) + { + x++; + continue; + } + mlx_put_pixel(game->screen->img, x, y, color); + x++; + } + y++; + } +} + +void render_sprites(t_render *render, t_game *game) +{ + int i; + + calculate_sprite_dist(game); + sort_sprites(game); + i = 0; + while (i < game->map->n_sprites) + { + cam_fraction(game, &game->map->sprites[i]); + draw_sprite(game, &game->map->sprites[i]); + i++; + } +} \ No newline at end of file diff --git a/src/screen.c b/src/screen.c index 31b05f8..2019167 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/05/08 12:09:03 by qmennen ### ########.fr */ +/* Updated: 2025/05/08 15:51:30 by qmennen ### ########.fr */ /* */ /* ************************************************************************** */ @@ -35,7 +35,6 @@ int screen_create(t_game **game) screen->background = mlx_new_image(screen->mlx, WIDTH, HEIGHT); if (!screen->background) return (FAILURE); - screen->hud = mlx_texture_to_image(mlx, mlx_load_png("./assets/overlay.png")); (*game)->screen = screen; return (SUCCESS); } diff --git a/src/util/initialize.c b/src/util/initialize.c index 2b79530..72f289c 100644 --- a/src/util/initialize.c +++ b/src/util/initialize.c @@ -1,17 +1,32 @@ /* ************************************************************************** */ /* */ -/* :::::::: */ -/* initialize.c :+: :+: */ -/* +:+ */ -/* By: qmennen +#+ */ -/* +#+ */ -/* Created: 2025/04/22 17:08:26 by qmennen #+# #+# */ -/* Updated: 2025/05/07 11:35:18 by whaffman ######## odam.nl */ +/* ::: :::::::: */ +/* initialize.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: qmennen +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/04/22 17:08:26 by qmennen #+# #+# */ +/* Updated: 2025/05/08 14:52:45 by qmennen ### ########.fr */ /* */ /* ************************************************************************** */ #include "cub3d.h" +static int init_temp(t_game **game) +{ + (*game)->map->sprites = malloc(sizeof(t_sprite)); + if (!(*game)->map->sprites) + return (FAILURE); + (*game)->map->sprites[0].n_frames = 1; + (*game)->map->sprites[0].pos.x = 3.5; + (*game)->map->sprites[0].pos.y = 3.5; + (*game)->map->sprites[0].dist = 0; + (*game)->map->sprites[0].texture = mlx_load_png("./assets/battery.png"); + (*game)->map->n_sprites = 1; + (*game)->screen->hud = mlx_texture_to_image((*game)->screen->mlx, mlx_load_png("./assets/overlay.png")); + return (SUCCESS); +} + int initialize_cub3d(t_game **game, const char *mapfile) { if (!game_create(game)) @@ -26,6 +41,8 @@ int initialize_cub3d(t_game **game, const char *mapfile) return (FAILURE); if (!keyboard_create(game)) return (FAILURE); + if (!init_temp(game)) + return (FAILURE); if (!screen_display((*game)->screen)) return (FAILURE); mlx_key_hook((*game)->screen->mlx, keyhandle, *game);