我无法让顶点围绕玩家正确旋转
I can not get vertices to rotate correctly around a player
我正在使用 C 和 SDL 从头开始创建经典射击游戏。我似乎 运行 遇到了一个我想不通的问题。
当我尝试围绕玩家旋转世界几何体时,它似乎没有正确旋转。
理论上玩家和顶点之间的距离在我执行旋转后应该保持不变,但在我的代码中似乎没有。
我在下面包含了我的代码的相关部分以及正在发生的事情的 gif。
我想了解这里发生了什么以及关于如何修复它的一些指导。
for (unsigned s = 0; s < sect->npoints; s++)
{
// Transform vertex relative to the player view.
// This will move the room relative to the player.
float vx1 = sect->vertex[s].x - player.where.x;
float vx2 = sect->vertex[s+1].x - player.where.x;
float vy1 = sect->vertex[s].y - player.where.y;
float vy2 = sect->vertex[s+1].y - player.where.y;
float test1 = vx1 * vx1 + vy1 * vy1;
float test2 = vx2 * vx2 + vy2 * vy2;
printf("%f %f\n", sqrt(test1), sqrt(test2));
// Rotate the room to the correct orientation using geometry of rotation
// We want to find t (tx1, tz1) coordinates given the players current orientation.
// P == player, v == the vertex in the sector
// )8 == the angle of the player
//
// We can get tx1 = vx1 * player cos - vy1 * player sin
// and get tz1 = vx1 * player sin - vy1 * player cos
// |............................
// ^|...t (tx1, tz1).............
// ||../........v (vx1, vy1).....
// y|./..........................
// 0|P)8.........................
// L-----------------------------
// 0 x -->
float pcos = player.anglecos;
float psin = player.anglesin;
float tx1 = vx1 * psin - vy1 * pcos;
float tz1 = vx1 * pcos - vy1 * psin;
float tx2 = vx2 * psin - vy2 * pcos;
float tz2 = vx2 * pcos - vy2 * psin;
test1 = tx1 * tx1 + tz1 * tz1;
test2 = tx2 * tx2 + tz2 * tz2;
printf("%f %f %f\n\n", sqrt(test1), sqrt(test2), player.angle);
...
// Perform the perspective transformation.
// This will make sure the correct field of view is being used.
// TOOD: Adjustible FOV
float xscale1 = hfov / tz1;
float yscale1 = vfov / tz1;
float xscale2 = hfov / tz2;
float yscale2 = vfov / tz2;
int x1 = ScreenWidth / 2 - (int)(tx1 * xscale1);
int x2 = ScreenWidth / 2 - (int)(tx2 * xscale2);
...
int ya = (x - x1) * (y2a-y1a) / (x2-x1) + y1a;
int yb = (x - x1) * (y2b-y1b) / (x2-x1) + y1b;
int cya = clamp(ya, ytop[x], ybottom[x]); // top
int cyb = clamp(yb, ytop[x], ybottom[x]); // bottom
rendervline(x, cya, cyb, wall_color);
}
...
// Elsewhere where I handle movement
// mouse aiming
int x, y;
SDL_GetRelativeMouseState(&x,&y);
player.angle += x * 0.03f;
...
player.anglesin = sinf(player.angle);
player.anglecos = cosf(player.angle);
以及玩家与边缘顶点之间距离的一些样本输出。
28.635642 31.304952
29.442936 29.505904 0.070000
我很接近问题是我在计算 z 轴时是减法而不是加法。
float tx1 = vx1 * psin - vy1 * pcos;
float tz1 = vx1 * pcos - vy1 * psin;
float tx2 = vx2 * psin - vy2 * pcos;
float tz2 = vx2 * pcos - vy2 * psin;
应该是这个
float tx1 = vx1 * psin - vy1 * pcos;
float tz1 = vx1 * pcos + vy1 * psin;
float tx2 = vx2 * psin - vy2 * pcos;
float tz2 = vx2 * pcos + vy2 * psin;
我正在使用 C 和 SDL 从头开始创建经典射击游戏。我似乎 运行 遇到了一个我想不通的问题。
当我尝试围绕玩家旋转世界几何体时,它似乎没有正确旋转。
理论上玩家和顶点之间的距离在我执行旋转后应该保持不变,但在我的代码中似乎没有。
我在下面包含了我的代码的相关部分以及正在发生的事情的 gif。
我想了解这里发生了什么以及关于如何修复它的一些指导。
for (unsigned s = 0; s < sect->npoints; s++)
{
// Transform vertex relative to the player view.
// This will move the room relative to the player.
float vx1 = sect->vertex[s].x - player.where.x;
float vx2 = sect->vertex[s+1].x - player.where.x;
float vy1 = sect->vertex[s].y - player.where.y;
float vy2 = sect->vertex[s+1].y - player.where.y;
float test1 = vx1 * vx1 + vy1 * vy1;
float test2 = vx2 * vx2 + vy2 * vy2;
printf("%f %f\n", sqrt(test1), sqrt(test2));
// Rotate the room to the correct orientation using geometry of rotation
// We want to find t (tx1, tz1) coordinates given the players current orientation.
// P == player, v == the vertex in the sector
// )8 == the angle of the player
//
// We can get tx1 = vx1 * player cos - vy1 * player sin
// and get tz1 = vx1 * player sin - vy1 * player cos
// |............................
// ^|...t (tx1, tz1).............
// ||../........v (vx1, vy1).....
// y|./..........................
// 0|P)8.........................
// L-----------------------------
// 0 x -->
float pcos = player.anglecos;
float psin = player.anglesin;
float tx1 = vx1 * psin - vy1 * pcos;
float tz1 = vx1 * pcos - vy1 * psin;
float tx2 = vx2 * psin - vy2 * pcos;
float tz2 = vx2 * pcos - vy2 * psin;
test1 = tx1 * tx1 + tz1 * tz1;
test2 = tx2 * tx2 + tz2 * tz2;
printf("%f %f %f\n\n", sqrt(test1), sqrt(test2), player.angle);
...
// Perform the perspective transformation.
// This will make sure the correct field of view is being used.
// TOOD: Adjustible FOV
float xscale1 = hfov / tz1;
float yscale1 = vfov / tz1;
float xscale2 = hfov / tz2;
float yscale2 = vfov / tz2;
int x1 = ScreenWidth / 2 - (int)(tx1 * xscale1);
int x2 = ScreenWidth / 2 - (int)(tx2 * xscale2);
...
int ya = (x - x1) * (y2a-y1a) / (x2-x1) + y1a;
int yb = (x - x1) * (y2b-y1b) / (x2-x1) + y1b;
int cya = clamp(ya, ytop[x], ybottom[x]); // top
int cyb = clamp(yb, ytop[x], ybottom[x]); // bottom
rendervline(x, cya, cyb, wall_color);
}
...
// Elsewhere where I handle movement
// mouse aiming
int x, y;
SDL_GetRelativeMouseState(&x,&y);
player.angle += x * 0.03f;
...
player.anglesin = sinf(player.angle);
player.anglecos = cosf(player.angle);
以及玩家与边缘顶点之间距离的一些样本输出。
28.635642 31.304952
29.442936 29.505904 0.070000
我很接近问题是我在计算 z 轴时是减法而不是加法。
float tx1 = vx1 * psin - vy1 * pcos;
float tz1 = vx1 * pcos - vy1 * psin;
float tx2 = vx2 * psin - vy2 * pcos;
float tz2 = vx2 * pcos - vy2 * psin;
应该是这个
float tx1 = vx1 * psin - vy1 * pcos;
float tz1 = vx1 * pcos + vy1 * psin;
float tx2 = vx2 * psin - vy2 * pcos;
float tz2 = vx2 * pcos + vy2 * psin;