/* ************************************************************************** */ /* */ /* :::::::: */ /* render_sprite.c :+: :+: */ /* +:+ */ /* By: whaffman +#+ */ /* +#+ */ /* Created: 2025/05/08 12:23:17 by qmennen #+# #+# */ /* Updated: 2025/05/08 23:18:06 by whaffman ######## odam.nl */ /* */ /* ************************************************************************** */ #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; index = (x + y * texture->width) * texture->bytes_per_pixel; dist = (dist > 1) * dist + (dist <= 1) * 1; alpha = (texture->pixels[index + 3] != 0) * (255.0 / dist); 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, t_render *render) { 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 <= 0) return; sprite_scale = 16.0 / sprite->dist; x_start = game->screen->width * 0.5 * (1.0 + sprite->cam_frac) - (sprite->texture->width * sprite_scale * 0.5); y_start = (game->screen->height - sprite->texture->height * sprite_scale )* 0.5; x_end = x_start + (sprite->texture->width * sprite_scale); y_end = y_start + (sprite->texture->height * sprite_scale); x = x_start; while (x < x_end) { if (x > 0 && x < game->screen->width && sprite->dist <= render[x].perp_dist) { y = y_start; tex_x = ((double)((x - x_start) / (double)(x_end - x_start))) * sprite->texture->width; while (y < y_end) { tex_y = ((double)((y- y_start) / (double)(y_end - y_start))) * sprite->texture->height; color = sample_texture_color(sprite->texture, (int)(tex_x), (int)(tex_y), sprite->dist); if (y > 0 && y < game->screen->height && (color & 0xFF) != 0) { mlx_put_pixel(game->screen->img, x, y, color); } y++; } } x++; } } 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], render); i++; } }