/* ************************************************************************** */ /* */ /* ::: :::::::: */ /* dda.c :+: :+: :+: */ /* +:+ +:+ +:+ */ /* By: erey-bet +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* 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); }