cub3d/src/render/render_sprite.c
2025-06-03 15:52:24 +02:00

124 lines
3.7 KiB
C

/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* render_sprite.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: qmennen <qmennen@student.codam.nl> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/05/08 12:23:17 by qmennen #+# #+# */
/* Updated: 2025/06/03 15:00:43 by qmennen ### ########.fr */
/* */
/* ************************************************************************** */
#include "render.h"
static void get_start_end(t_game *game,
t_sprite *sprite, t_vec2_int *start, t_vec2_int *end)
{
double sprite_scale;
sprite_scale = game->screen->height / sprite->dist
/ sprite->texture->height;
start->x = 0.5 * (game->screen->width * (1.0 + sprite->cam_frac)
- sprite->texture->width / sprite->n_frames * sprite_scale);
start->y = 0.5 * (game->screen->height
- sprite->texture->height * sprite_scale);
end->x = start->x;
end->x += sprite->texture->width / sprite->n_frames * sprite_scale;
end->y = start->y + sprite->texture->height * sprite_scale;
}
static int sprite_visible(t_game *game,
t_sprite *sprite, t_render *render, int x)
{
return (!isnan(sprite->cam_frac)
&& sprite->dist > MIN_SPRITE_DIST
&& x > 0
&& x < game->screen->width
&& sprite->dist <= render[x].perp_dist);
}
static void draw_sprite_column(
t_game *game, t_sprite *sprite, t_render *render,
t_sprite_column column)
{
t_vec2_int tex;
t_vec2 inv_range;
int y;
unsigned int color;
int frame;
frame = (game->elapsed_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);
sprite->alpha = calculate_alpha(column.start.x,
column.start.y, sprite->dist);
tex.x = column.x - column.start.x;
tex.x *= sprite->texture->width / sprite->n_frames;
tex.x *= inv_range.x;
y = column.start.y;
while (y < column.end.y)
{
tex.y = (y - column.start.y) * sprite->texture->height;
tex.y *= inv_range.y;
color = sample_texture_color(sprite, tex, frame);
if (y > 0 && y < game->screen->height && (color & 0xFF) != 0)
mlx_put_pixel(game->screen->img, column.x, y, color);
y++;
}
}
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;
t_vec2_int end;
t_sprite_column column;
int x;
if (isnan(sprite->cam_frac) || sprite->dist <= MIN_SPRITE_DIST)
return ;
get_start_end(game, sprite, &start, &end);
x = start.x;
while (x < end.x)
{
if (sprite_visible(game, sprite, render, x))
{
handle_flash(sprite, game);
column.start = start;
column.end = end;
column.x = x;
draw_sprite_column(game, sprite, render, column);
}
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)
{
if (game->map->sprites[i].type == SPRITE_TYPE_DISABLED
|| game->map->sprites[i].type == SPRITE_TYPE_COLLECTED)
{
i++;
continue ;
}
cam_fraction(game, &game->map->sprites[i]);
draw_sprite(game, &game->map->sprites[i], render);
i++;
}
}