7.FPS游戏自瞄透视之准星算法 任鸟飞逆向 任鸟飞逆向 知道了准星的变化规律: 1.准星水平位置摇摆角 正北是π,逆时针逐渐减小,正南是0,继续逆时针减小到正北为-π π和-π重叠 (正北方向Y轴逐渐增加,正东方向X轴逐渐增加) 2.准星高度位置俯冲角 正上方是0.5π,正下方是-0.5π 我们就要为其写瞄准的算法了。 假设人物的坐标是:人物.fX,人物.fY,人物.fZ 目标的坐标是:怪物X,怪物Y,怪物Z。 首先我们写准星水平位置摇摆角 这个只考虑X,Y的平面即可不存在高度的问题 我们把坐标系分成四个象限来分别计算, 理论上是可以统一计算的, 但是我们为了更多没有数学基础的同学也能看懂,把其分层四种可能计算更容易理解 ①如果怪物X > 人物.fX 并且 怪物Y > 人物.fY 那么怪物处在第一象限也就是我们的东北方 图中 角a 根据正切公式 等于 atan2(怪物Y-人物.fY,怪物X-人物.fX) 返回值为-π到π ,图中第一象限范围内 就是返回值 从 π/2 到 0 ,顺时针减少 而我们朝向在第一象限是 -π 到 -π/2 顺时针增加的 我们要把我们得到的角度换算成他的变化规律 才能正确表示准星位置 所以第一步我们就要对角度取负 让其变化方向一致 都为顺时针增加 - atan2(怪物Y-人物.fY,怪物X-人物.fX) 的变化范围就成了 -π/2 到 0 顺时针增加 但是范围还是有差别 那么第二步,加上偏差的-π/2 使其变化规律相同 - atan2(怪物Y-人物.fY,怪物X-人物.fX) -π/2 这样就可以自动瞄准了。 ②如果怪物X < 人物.fX 并且 怪物Y > 人物.fY 那么怪物处在第二象限也就是我们的西北方 角度依然等于 atan2(怪物Y-人物.fY,怪物X-人物.fX) 图中第二象限范围内 返回值 从 0 到 π/2 ,顺时针增加 第一步,和我们的范围 π/2 到 π 顺时针增加 变化方向一致,不需要取负 第二步,偏差π/2 加上即可 最终 atan2(怪物Y-人物.fY,怪物X-人物.fX)+π/2 ③如果怪物X < 人物.fX 并且 怪物Y < 人物.fY 那么怪物处在第三象限也就是我们的西南方 角度依然等于 atan2(怪物Y-人物.fY,怪物X-人物.fX) 图中第三象限范围内 返回值 从 π/2到0 ,顺时针减少 第一步,和我们的范围 0到 π/2 顺时针增加 变化方向不一致,取负使其一致 -atan2(怪物Y-人物.fY,怪物X-人物.fX) 变成 -π/2 到0 顺时针增加 第二步,偏差π/2 加上即可 最终 -atan2(怪物Y-人物.fY,怪物X-人物.fX)+π/2 ④如果怪物X > 人物.fX 并且 怪物Y < 人物.fY 那么怪物处在第四象限也就是我们的东南方 角度依然等于 atan2(怪物Y-人物.fY,怪物X-人物.fX) 图中第四象限范围内 返回值 从 0 到π/2 ,顺时针增加 第一步,和我们的范围 -π/2都0 顺时针增加 变化方向一致,不用取负 第二步,偏差 -π/2 加上即可 最终 atan2(怪物Y-人物.fY,怪物X-人物.fX)-π/2 然后我们写准星高度位置俯冲角 道理一样的 ,不过是分为抬头还是低头 不过这次 求正切角度的2个边不再是 怪物Y-人物.fY 和 怪物X-人物.fX 而是 怪物Z-人物.fZ 和 水平距离了 水平距离 = sqrt((怪物X-人物.fX)*(怪物X-人物.fX)+(怪物Y-人物.fY)*(怪物Y-人物.fY)); 抬头情况下 俯视角 = atan2(怪物Z-人物.fZ,水平距离); 低头情况下 俯视角 = - atan2(人物.fZ-怪物Z,水平距离); 总结代码如下: void Call_自动瞄准(FLOAT 怪物X,FLOAT 怪物Y,FLOAT 怪物Z) { T人物属性 人物; 人物.初始化(); FLOAT 水平角; if (怪物X > 人物.fX && 怪物Y > 人物.fY)//第一象限 { 水平角=(FLOAT)(- atan2(怪物Y-人物.fY,怪物X-人物.fX)-3.1415926/2); } if (怪物X < 人物.fX && 怪物Y > 人物.fY)//第二象限 { 水平角=(FLOAT)(atan2(怪物Y-人物.fY,人物.fX-怪物X)+3.1415926/2); } if (怪物X < 人物.fX && 怪物Y < 人物.fY)//第三象限 { 水平角=(FLOAT)(3.1415926/2-atan2(人物.fY-怪物Y,人物.fX-怪物X)); } if (怪物X > 人物.fX && 怪物Y < 人物.fY)//第四象限 { 水平角=(FLOAT)(atan2(人物.fY-怪物Y,怪物X-人物.fX)-3.1415926/2); } FLOAT 俯视角; FLOAT 水平距离; 水平距离 = sqrt((怪物X-人物.fX)*(怪物X-人物.fX)+(怪物Y-人物.fY)*(怪物Y-人物.fY)); if (怪物Z > 人物.fZ) { 俯视角 = atan2(怪物Z-人物.fZ,水平距离); } if (怪物Z < 人物.fZ) { 俯视角 = 0 - atan2(人物.fZ-怪物Z,水平距离); } DWORD 模块句柄 = (DWORD)GetModuleHandleA("Crossout.exe"); *(FLOAT*)(模块句柄 + Base_XY朝向基地址) = 水平角; //计算出来的朝向值 写入内存 *(FLOAT*)(模块句柄 + Base_Z朝向基地址) = 俯视角; //计算出来的朝向值 写入内存 }
逆向交流qun:453769015
联系我时,请说是在 挂海论坛 上看到的,谢谢! |