148 lines
4.1 KiB
C
148 lines
4.1 KiB
C
/* ************************************************************************** */
|
|
/* */
|
|
/* :::::::: */
|
|
/* render_sprite.c :+: :+: */
|
|
/* +:+ */
|
|
/* By: whaffman <whaffman@student.codam.nl> +#+ */
|
|
/* +#+ */
|
|
/* 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++;
|
|
}
|
|
} |