185 lines
4.9 KiB
C
185 lines
4.9 KiB
C
/* ************************************************************************** */
|
|
/* */
|
|
/* ::: :::::::: */
|
|
/* dda.c :+: :+: :+: */
|
|
/* +:+ +:+ +:+ */
|
|
/* By: erey-bet <marvin@42.fr> +#+ +:+ +#+ */
|
|
/* +#+#+#+#+#+ +#+ */
|
|
/* Created: 2023/05/02 15:49:00 by erey-bet #+# #+# */
|
|
/* Updated: 2023/05/10 13:40:52 by erey-bet ### ########.fr */
|
|
/* */
|
|
/* ************************************************************************** */
|
|
|
|
#include "game.h"
|
|
|
|
double ft_abs(double nb)
|
|
{
|
|
if (nb < 0)
|
|
return (-nb);
|
|
return (nb);
|
|
}
|
|
|
|
void init_dda(t_game *game, t_dda *dda)
|
|
{
|
|
t_ray *ray;
|
|
t_ply *ply;
|
|
|
|
ray = &game->ray;
|
|
ply = &game->ply;
|
|
dda->map_x = (int)ply->pos_x;
|
|
dda->map_y = (int)ply->pos_y;
|
|
if (ray->dir_x == 0)
|
|
dda->delta_dist_x = 1e30;
|
|
else
|
|
dda->delta_dist_x = ft_abs(1 / ray->dir_x);
|
|
if (ray->dir_y == 0)
|
|
dda->delta_dist_y = 1e30;
|
|
else
|
|
dda->delta_dist_y = ft_abs(1 / ray->dir_y);
|
|
dda->step_x = 1;
|
|
dda->step_y = 1;
|
|
if (ray->dir_x < 0)
|
|
{
|
|
dda->step_x = -1;
|
|
dda->side_dist_x = (ply->pos_x - dda->map_x) * dda->delta_dist_x;
|
|
}
|
|
else
|
|
dda->side_dist_x = (dda->map_x + 1.0 - ply->pos_x) * dda->delta_dist_x;
|
|
if (ray->dir_y < 0)
|
|
{
|
|
dda->step_y = -1;
|
|
dda->side_dist_y = (ply->pos_y - dda->map_y) * dda->delta_dist_y;
|
|
}
|
|
else
|
|
dda->side_dist_y = (dda->map_y + 1.0 - ply->pos_y) * dda->delta_dist_y;
|
|
dda->hit = 0;
|
|
}
|
|
|
|
void loop_dda(t_game *game, t_dda *dda)
|
|
{
|
|
while (dda->hit == 0)
|
|
{
|
|
if (dda->side_dist_x < dda->side_dist_y)
|
|
{
|
|
dda->side_dist_x += dda->delta_dist_x;
|
|
dda->map_x += dda->step_x;
|
|
dda->side = 0;
|
|
}
|
|
else
|
|
{
|
|
dda->side_dist_y += dda->delta_dist_y;
|
|
dda->map_y += dda->step_y;
|
|
dda->side = 1;
|
|
}
|
|
if (dda->map_x < 0 || dda->map_y < 0
|
|
|| dda->map_y >= (int)game->map.size_y
|
|
|| dda->map_x >= (int)ft_strlen(game->map.map[dda->map_y]))
|
|
{
|
|
dda->perp_wall_dist = 1e30;
|
|
return ;
|
|
}
|
|
if (game->map.map[dda->map_y][dda->map_x] == '1')
|
|
dda->hit = 1;
|
|
}
|
|
if(dda->side == 0)
|
|
dda->perp_wall_dist = dda->side_dist_x - dda->delta_dist_x;
|
|
else
|
|
dda->perp_wall_dist = dda->side_dist_y - dda->delta_dist_y;
|
|
}
|
|
|
|
void ray_dda(t_dda *dda)
|
|
{
|
|
if (dda->perp_wall_dist == 0)
|
|
dda->perp_wall_dist = 1e30;
|
|
dda->line_height = (int)(HEIGHT / dda->perp_wall_dist);
|
|
dda->draw_start = -(dda->line_height) / 2 + HEIGHT / 2;
|
|
if(dda->draw_start < 0)
|
|
dda->draw_start = 0;
|
|
dda->draw_end = dda->line_height / 2 + HEIGHT / 2;
|
|
if(dda->draw_end >= HEIGHT)
|
|
dda->draw_end = HEIGHT - 1;
|
|
}
|
|
|
|
unsigned int get_rgba(int r, int g, int b, int a)
|
|
{
|
|
return (r << 24 | g << 16 | b << 8 | a);
|
|
}
|
|
|
|
|
|
static uint32_t switch_color_bytes(uint32_t bad)
|
|
{
|
|
uint32_t good;
|
|
|
|
good = ((bad & 0xff) << 24) | (((bad >> 8) & 0xff) << 16)
|
|
| (((bad >> 16) & 0xff) << 8) | bad >> 24;
|
|
return (good);
|
|
}
|
|
|
|
uint32_t get_pixel_color(mlx_texture_t *texture, uint32_t x, uint32_t y) {
|
|
return switch_color_bytes(*(uint32_t*)(texture->pixels + (y * texture->width + x) * texture->bytes_per_pixel));
|
|
}
|
|
|
|
int get_texture_side(t_dda *dda)
|
|
{
|
|
if (dda->side == 0 && dda->step_x < 0)
|
|
return (0);
|
|
if (dda->side == 0 && dda->step_x > 0)
|
|
return (1);
|
|
if (dda->side == 1 && dda->step_y < 0)
|
|
return (2);
|
|
if (dda->side == 1 && dda->step_y > 0)
|
|
return (3);
|
|
return (0);
|
|
}
|
|
|
|
void draw_texture(t_game *game, t_dda *dda, double x)
|
|
{
|
|
t_texture_draw tex;
|
|
t_ply *ply;
|
|
int y;
|
|
|
|
ply = &game->ply;
|
|
tex.texture = game->textures[get_texture_side(dda)];
|
|
if (dda->side == 0)
|
|
tex.wall_x = ply->pos_y + dda->perp_wall_dist * game->ray.dir_y;
|
|
else
|
|
tex.wall_x = ply->pos_x + dda->perp_wall_dist * game->ray.dir_x;
|
|
tex.wall_x -= floor(tex.wall_x);
|
|
tex.x = (int)(tex.wall_x * (double)tex.texture->width);
|
|
if ((dda->side == 0 && game->ray.dir_x > 0)
|
|
|| (dda->side == 1 && game->ray.dir_y < 0))
|
|
tex.x = tex.texture->width - tex.x - 1;
|
|
tex.step = 1.0 * tex.texture->height / dda->line_height;
|
|
tex.pos = (dda->draw_start - game->window->height / 2 + dda->line_height / 2) * tex.step;
|
|
y = dda->draw_start - 1;
|
|
while (++y < dda->draw_end)
|
|
{
|
|
tex.y = (int)tex.pos & (tex.texture->height - 1);
|
|
tex.pos += tex.step;
|
|
mlx_put_pixel(game->window, x, y, get_pixel_color(tex.texture, tex.x, tex.y));
|
|
}
|
|
}
|
|
|
|
void draw(t_game *game, t_dda *dda, int x)
|
|
{
|
|
int y;
|
|
|
|
y = -1;
|
|
while (++y < dda->draw_start)
|
|
mlx_put_pixel(game->window, x, y, game->map.color_bot);
|
|
draw_texture(game, dda, x);
|
|
y = dda->draw_end - 1;
|
|
while (++y < HEIGHT)
|
|
mlx_put_pixel(game->window, x, y, game->map.color_top);
|
|
}
|
|
|
|
void dda(t_game *game, int x)
|
|
{
|
|
t_dda dda;
|
|
|
|
init_dda(game, &dda);
|
|
loop_dda(game, &dda);
|
|
ray_dda(&dda);
|
|
draw(game, &dda, x);
|
|
}
|