# define GRID_SIZE 64
// TODO: this comment
# define EPSILON 0.0001
// one degree in radians
# define ONE_DEGREE 0.0174532925
// Screen width
# define SCREEN_WIDTH 720
// Screen Height
# define SCREEN_HEIGHT 480
// Scale Factor for height of walls
# define SCALE_FACTOR 0.05
typedef struct s_ray_data
{
int mx;
int my;
int mp;
int dof;
double rx;
double ry;
double ra;
double xo;
double yo;
double a_tan;
double n_tan;
double hx;
double hy;
double dist_h;
double vx;
double vy;
double dist_v;
} t_ray_data;
typedef struct s_ray_result
{
double dist;
double x;
double y;
int object;
} t_ray_result;
typedef struct s_ray
{
int color;
int direction;
int object;
double distance;
} t_ray;
double mes_dist(double ax, double ay, double bx, double by)
{
return (sqrt((bx - ax) * (bx - ax) + (by - ay) * (by - ay)));
}
void calculate_horizontal_intercept(t_player_data *p, t_ray_data *rd)
{
rd->dof = 0;
rd->a_tan = -1 / tan(rd->ra);
if (rd->ra > M_PI)
{
rd->ry = (((int)p->posy / GRID_SIZE) * GRID_SIZE) - 0.0001;
rd->rx = (p->posy - rd->ry) * rd->a_tan + p->posx;
rd->yo = -GRID_SIZE;
rd->xo = -rd->yo * rd->a_tan;
}
if (rd->ra < M_PI)
{
rd->ry = (((int)p->posy / GRID_SIZE) * GRID_SIZE) + GRID_SIZE;
rd->rx = (p->posy - rd->ry) * rd->a_tan + p->posx;
rd->yo = GRID_SIZE;
rd->xo = -rd->yo * rd->a_tan;
}
if (fabs(rd->ra) < EPSILON || fabs(rd->ra - M_PI) < EPSILON)
{
rd->rx = p->posx;
rd->ry = p->posy;
rd->dof = 8;
}
}
void calculate_vertical_intercept(t_player_data *p, t_ray_data *rd)
{
rd->dof = 0;
rd->n_tan = -tan(rd->ra);
if (rd->ra > M_PI_2 && rd->ra < 3 * M_PI_2)
{
rd->rx = (((int)p->posx / GRID_SIZE) * GRID_SIZE) - 0.0001;
rd->ry = (p->posx - rd->rx) * rd->n_tan + p->posy;
rd->xo = -GRID_SIZE;
rd->yo = -rd->xo * rd->n_tan;
}
if (rd->ra < M_PI_2 || rd->ra > 3 * M_PI_2)
{
rd->rx = (((int)p->posx / GRID_SIZE) * GRID_SIZE) + GRID_SIZE;
rd->ry = (p->posx - rd->rx) * rd->n_tan + p->posy;
rd->xo = GRID_SIZE;
rd->yo = -rd->xo * rd->n_tan;
}
if (fabs(rd->ra - M_PI_2) < EPSILON || fabs(rd->ra - 3 * M_PI_2) < EPSILON)
{
rd->rx = p->posx;
rd->ry = p->posy;
rd->dof = 8;
}
}
static void calculate_ray_data(t_player_data *p, t_ray_data *rd, t_minimap *m,
t_ray_result *res)
{
res->dist = 0.;
res->x = p->posx;
res->y = p->posy;
while (rd->dof < 8)
{
rd->mx = (int)(rd->rx) / GRID_SIZE;
rd->my = (int)(rd->ry) / GRID_SIZE;
rd->mp = rd->my * m->map_x + rd->mx;
if (rd->mp > 0 && rd->mx >= 0 && rd->mx < m->map_x && rd->my >= 0
&& rd->my < m->map_y && object_finder(m, rd, res))
{
res->x = rd->rx;
res->y = rd->ry;
res->dist = mes_dist(p->posx, p->posy, res->x, res->y);
rd->dof = 8;
}
else
{
rd->rx += rd->xo;
rd->ry += rd->yo;
rd->dof++;
}
}
if (res->dist == 0.)
res->dist = INFINITY;
}
void draw_rays(t_player_data *player, t_minimap *map, double angle, t_ray *rs)
{
t_ray_data ray_data;
t_ray_result result_h;
t_ray_result result_v;
double ca;
ray_data.ra = angle;
ca = player->playerangle - ray_data.ra;
if (ca < 0)
ca += 2 * M_PI;
if (ca > 2 * M_PI)
ca -= 2 * M_PI;
calculate_horizontal_intercept(player, &ray_data);
calculate_ray_data(player, &ray_data, map, &result_h);
calculate_vertical_intercept(player, &ray_data);
calculate_ray_data(player, &ray_data, map, &result_v);
if (result_h.dist < result_v.dist)
{
ray_data.rx = result_h.x;
ray_data.ry = result_h.y;
rs->object = result_h.object;
rs->color = 0xFF0000;
direction_setter(rs, true, &ray_data, player);
}
else
{
ray_data.rx = result_v.x;
ray_data.ry = result_v.y;
rs->object = result_v.object;
rs->color = 0x800000;
direction_setter(rs, false, &ray_data, player);
}
rs->distance = mes_dist(player->posx, player->posy, ray_data.rx,
ray_data.ry);
rs->distance = rs->distance * cos(ca);
}
void draw_ceiling(int x, int segment_width, int y_start, t_mlx *mlx)
{
int y;
int x_current;
y = 0;
while (y < y_start)
{
x_current = x;
while (x_current < x + segment_width)
{
my_mlx_pixel_put(mlx, x_current, y, rgb_to_hex(mlx->scene.c_clr));
x_current++;
}
y++;
}
}
void draw_walls(int x, int y_start, int y_end, t_mlx *mlx)
{
int y;
int x_current;
int segment_width;
segment_width = SCREEN_WIDTH / mlx->map->player->fov;
x_current = x;
while (x_current < x + segment_width)
{
y = y_start;
while (y < y_end)
{
my_mlx_pixel_put(mlx, x_current, y, mlx->wall_color);
y++;
}
x_current++;
}
}
void draw_floor(int x, int segment_width, int y_end, t_mlx *mlx)
{
int y;
int x_current;
y = y_end;
while (y < SCREEN_HEIGHT)
{
x_current = x;
while (x_current < x + segment_width)
{
my_mlx_pixel_put(mlx, x_current, y, rgb_to_hex(mlx->scene.f_clr));
x_current++;
}
y++;
}
}
void draw_wall_segment_to_image(int x, float distance, t_mlx *mlx, int color)
{
int wall_height;
int y_start;
int y_end;
int segment_width;
segment_width = SCREEN_WIDTH / mlx->map->player->fov;
wall_height = (int)(SCREEN_HEIGHT / (distance * SCALE_FACTOR));
y_start = (SCREEN_HEIGHT - wall_height) / 2;
y_end = y_start + wall_height;
mlx->wall_color = color;
draw_ceiling(x, segment_width, y_start, mlx);
draw_walls(x, y_start, y_end, mlx);
draw_floor(x, segment_width, y_end, mlx);
}
void walls_3d(t_minimap *map, t_player_data *player, t_mlx *mlx)
{
double angle;
int i;
int segment_width;
t_ray ray_result;
segment_width = SCREEN_WIDTH / player->fov;
i = 0;
angle = player->playerangle - ONE_DEGREE * (player->fov / 2);
while (i <= player->fov)
{
if (angle < 0)
angle += 2 * M_PI;
if (angle > 2 * M_PI)
angle -= 2 * M_PI;
draw_rays(player, map, angle, &ray_result);
draw_wall_segment_to_image(i * segment_width, ray_result.distance, mlx,
ray_result.color);
angle += ONE_DEGREE;
i++;
}
}
当我靠近一面向我弯曲的墙壁时,我仍然有一些扭曲。如果我站在一堵长墙旁边,看起来它在近距离处向我弯曲,而在远处则弯曲得有点向外。只有当我站在它旁边的某个角度时才会发生这种情况。当我直视它时就没事了。
我尝试了距离 = 距离 * cos(ca),其中 ca 是玩家角度 - 射线角度。我还尝试使用相机飞机进行一些工作,但无法正常工作。降低视场角似乎也有一点帮助,但我希望人们在设置中拥有一个视场角滑块。
你计算了距离的平方吗?
物体的大小取决于(1 / 距离^2)
我猜它在“mes_dist”函数中被取消了
注意:请使用注释线以及曲线的含义,您可以用图片来提问吗