我正在制作一个简单的游戏,像沃尔芬斯坦3d在C上使用光线投射。为了计算射线的长度,我使用了DDA算法。我应用代码的一部分,计算射线的长度和墙壁的大小的垂直线,射线击中。如何优化和改进代码?
/*
** Function: void calculate()
**
** Arguments: main struct and i
**
** return: void
**
** Description: The raycasting loop is a for loop that goes through every x,
** so there is a calculation for every vertical stripe of the screen.
*/
void calculate(t_cub3d *cub)
{
int i;
i = 0;
while (i < cub->window.res_width)
{
calculate_cam(cub, &i);
// field_x and field_y represent the current square of the map the ray is in.
cub->field.field_x = cub->player.x_pos;
cub->field.field_y = cub->player.y_pos;
calculate_ray_dir(cub);
calculate_step(cub);
calculate_wall(cub);
calculate_height(cub);
draw(cub, i);
i++;
}
calculate_sprite(cub);
}
/*
** Function: void calculate_cam()
**
** Arguments: main struct, variable counter(width)
**
** return: void
**
** Description: x_camera is the x-coordinate on the camera plane
** that the current x-coordinate of the screen represents, done this way
** so that the right side of the screen will get coordinate 1, the center
** of the screen gets coordinate 0, and the left side of the screen gets coordinate -1
*/
void calculate_cam(t_cub3d *cub, int *i)
{
cub->camera.x_camera = 2 * *i / (double)(cub->window.res_width) - 1;
cub->ray.dir_ray_x = cub->player.x_dir + cub->camera.x_plane * \
cub->camera.x_camera;
cub->ray.dir_ray_y = cub->player.y_dir + cub->camera.y_plane * \
cub->camera.x_camera;
}
/*
** Function: void calculate_ray_dir()
**
** Arguments: main struct
**
** return: void
**
** Description: x_deltaDist and y_deltaDist are the distance the ray
** has to travel to go from 1 x-side to the next x-side, or from 1 y-side
** to the next y-side.
*/
void calculate_ray_dir(t_cub3d *cub)
{
if (cub->ray.dir_ray_y == 0)
cub->ray.x_deltadist = 0;
else
{
if (cub->ray.dir_ray_x == 0)
cub->ray.x_deltadist = 1;
else
cub->ray.x_deltadist = fabs(1 / cub->ray.dir_ray_x);
}
if (cub->ray.dir_ray_x == 0)
cub->ray.y_deltadist = 0;
else
{
if (cub->ray.dir_ray_y == 0)
cub->ray.y_deltadist = 1;
else
cub->ray.y_deltadist = fabs(1 / cub->ray.dir_ray_y);
}
}
/*
** Function: void calculate_step()
**
** Arguments: main struct
**
** return: void
**
** Description: x_sideDist and y_sideDist are initially the distance
** the ray has to travel from its start position to the first x-side and
** the first y-side.
*/
void calculate_step(t_cub3d *cub)
{
if (cub->ray.dir_ray_x < 0)
{
cub->ray.x_ray_step = -1;
cub->ray.x_sidedist = (cub->player.x_pos - (double)(cub->field.field_x))
* cub->ray.x_deltadist;
}
else
{
cub->ray.x_ray_step = 1;
cub->ray.x_sidedist = (((double)(cub->field.field_x) + 1.0 - \
cub->player.x_pos) * cub->ray.x_deltadist);
}
if (cub->ray.dir_ray_y < 0)
{
cub->ray.y_ray_step = -1;
cub->ray.y_sidedist = (cub->player.y_pos - (double)(cub->field.field_y))
* cub->ray.y_deltadist;
}
else
{
cub->ray.y_ray_step = 1;
cub->ray.y_sidedist = ((double)(cub->field.field_y) + 1.0 - \
cub->player.y_pos) * cub->ray.y_deltadist;
}
}
/*
** Function: void calculate_wall()
**
** Arguments: main struct
**
** return: void
**
** Description: DDA algorithm. It's a loop that increments the ray with 1 square
** every time, until a wall is hit.
*/
void calculate_wall(t_cub3d *cub)
{
int is_wall;
is_wall = 0;
cub->window.side = 0;
while (is_wall == 0)
{
if (cub->ray.x_sidedist < cub->ray.y_sidedist)
{
cub->ray.x_sidedist += cub->ray.x_deltadist;
cub->field.field_x += cub->ray.x_ray_step;
cub->window.side = 0;
}
else
{
cub->ray.y_sidedist += cub->ray.y_deltadist;
cub->field.field_y += cub->ray.y_ray_step;
cub->window.side = 1;
}
if (cub->field.map[cub->field.field_y][cub->field.field_x] == '1')
is_wall = 1;
}
calculate_distto_wall(cub);
}
/*
** Function: void calculate_distto_wall()
**
** Arguments: main struct
**
** return: void
**
** Description: calculate the distance of the ray to the wall
*/
void calculate_distto_wall(t_cub3d *cub)
{
if (cub->window.side == 0)
{
cub->ray.wall_dist = ((double)(cub->field.field_x) - cub->player.x_pos \
+ (1 - cub->ray.x_ray_step) / 2) / cub->ray.dir_ray_x;
}
else
{
cub->ray.wall_dist = ((double)(cub->field.field_y) - cub->player.y_pos \
+ (1 - cub->ray.y_ray_step) / 2) / cub->ray.dir_ray_y;
}
}
/*
** Function: void calculate_height()
**
** Arguments: main struct
**
** return: void
**
** Description: calculate the height of the line that has to be
** drawn on screen
*/
void calculate_height(t_cub3d *cub)
{
cub->window.height_ln = (int)(cub->window.res_height / cub->ray.wall_dist);
cub->window.top_wall = (cub->window.height_ln * -1) / 2 + \
cub->window.res_height / 2;
if (cub->window.top_wall < 0)
cub->window.top_wall = 0;
cub->window.bottom_wall = cub->window.height_ln / 2 + \
cub->window.res_height / 2;
if (cub->window.bottom_wall >= cub->window.res_height)
cub->window.bottom_wall = cub->window.res_height - 1;
}发布于 2021-02-12 22:04:33
看起来你用一些特别的方式来记录你的函数。添加这些文档是非常好的,但是有一些工具使得它更有用,比如含氧。一旦您重新格式化您的评论遵循DO2语法,那么您就可以使用D氧气工具生成PDF、HTML和其他各种格式的文档。它还可以检查文档是否正确,例如,是否记录了所有参数。它已经在第一个函数中找到了一个错误:在函数参数的描述中使用mentino i,但是没有这样的东西。
传递整数
为什么要引用i传递calculate_sam()?您应该按值传递它,否则您将支付不必要的指针取消引用的费用。
您应该尝试为函数提供更多的描述性名称。命名所有的calculate_something()并不是很有用,因为计算基本上是计算机一直在做的事情。看起来,calculate()实际上导致了绘制所有东西,因为它调用了draw()。所以也许应该用类似于draw_scene()的名字来代替?draw()应该是draw_column()吗?
为什么有x_pos和x_plane,但是field_x呢?有一个一致的顺序词,使它更容易阅读你的代码。但是,field.field_x中也有冗余,也许可以重命名它,这样您就可以编写field.x了?
cub是什么?它代表一个立方体吗?如果是这样的话,不要随意地从一个单词中删除一个字母,稍后您可能会后悔。
此外,如果有一个包含坐标的变量,则使用x和y而不是i。
您的函数不返回任何内容,而是修改指向的对象。尽管您可能认为这会将事情保持在一起,但这实际上会使它们更难使用,并且可能会导致大量临时变量被放入t_cub3d中,这将浪费内存。尝试让函数return它们的结果,并且只将这些变量传递给它们需要使用的变量。
例如,calculate_cam()似乎只将x_camera计算为一个临时值,而其他代码(据我所见)所使用的唯一东西是射线的方向。因此,假设cub->ray有r_ray类型,我会写:
t_ray calculate_cam(const t_cub3d *cub, int x)
{
int x_camera = 2.0 * x / cub->window.res_width - 1;
t_ray ray;
ray.dir_ray_x = cub->player.x_dir + cub->camera.x_plane * x_camera;
ray.dir_ray_y = cub->player.y_dir + cub->camera.y_plane * x_camera;
return ray;
}bool 当您有一个包含一个值的变量,该值应该表示"true“或"false",请使用bool from <stdbool.h>。例如,is_wall是一个很好的候选者。
for而不是while (如果合适的话)for-statement的优点是可以明确地将初始值、结束条件和增量放在循环的顶部。所以在calculate()中,我会写:
for (int i = 0; i < cub->window.res_width; i++)
{
...
}https://codereview.stackexchange.com/questions/255913
复制相似问题