[代码中的数学]CSGO自瞄原理
本帖最后由 Keing 于 2019-1-20 15:31 编辑说到FPS游戏的自瞄,大家都会想到读玩家的坐标,然后将坐标转化为屏幕坐标,再移动鼠标,其实这个有很大的缺陷,而且过程也比较麻烦,分辨率一换又要出问题
还有一种自瞄方法,现在CSGO大多数自瞄都是这样一个原理,获得敌人和自己的坐标,通过坐标来计算角度,通过写角度来实现自瞄
目前通用的计算角度函数是这样的
void CalcAngle( float *src, float *dst, float *angles )
{
double delta = { (src-dst), (src-dst), (src-dst) };
double hyp = sqrt(delta*delta + delta*delta);
angles = (float) (asinf(delta/hyp) * (180/3.1415926));
angles = (float) (atanf(delta/delta) * (180/3.1415926));
angles = 0.0f;
if(delta >= 0.0) { angles += 180.0f; }
}
不过我今天要讲的是另一种算法,但是也相差不多
图上是两个玩家在三维上的位置,分别是A(-4,-2,1),B(4,2,1)
如果B是我们自己,而A是敌人,我们可以通过计算向量BA来得到两个玩家之间的距离,向量BA=A-B=(8,4,1),计算出向量BA后我们可以把我们自己也就是B当成原点坐标重新建立一个三维坐标系,如下图:
而敌人的坐标就是我们求出来的向量了
给大家简单介绍一个关于三维的概念:
· pitch是围绕X轴旋转,也叫做俯仰角
· yaw是围绕Y轴旋转,也叫做偏航角
以人物角色看,yaw是左右偏动,而picth是上下偏动,,在游戏中角度都是固定的一个方向,偏航和我们学习的二维坐标一样的,0°,90°,180°,270°,,而俯仰正Z轴是-90°,负Z轴是90°,俯仰可能和我们平时认知有点不一样,,不过不重要,我们继续
红色和X轴夹角我们称之为yaw,可以通过arctan(y/x)来计算出,而图中 yaw = arctan(4/8) ≈ 26°
蓝色和红色夹角我们称之为pitch,可以通过arcsin(z/红色),而 红色 = sqrt(x2 + y2) 所以 pitch = srcsin(2/(sqrt(82+42))) ≈ 6.37°
刚刚说过Z轴正半轴是-90°,而我们算出来是6.37°,很明显,如果俯仰以6.37°来写,那么我们的视角会朝下移动,所以我们要给俯仰度数取反 pitch = arcsin(z/红色) * -1
大家可能以为到这儿就结束了,其实不然,还有另外一种情况,我们继续往下看
如果最初我们是以A为我们玩家本身,B是敌人,那么我们要求的向量就是向量AB了,而向量AB = B - A = (-8,-4,1)
这样我们就可以以A为原点,敌人B的位置就是向量AB取成点的坐标,同样的道理我们计算出红线 和 X 轴负半轴的夹角为 -26°,刚刚说到偏航是X轴开始为0°,如果我们直接写入-36°,那么玩家视觉必定转向的是第四象限而不是第三象限,所以我们就需要在算法里面多加一条判断 (敌人-我) 的X是否小于等于0 ,如果满足 yaw = yaw + 180°
我们刚刚算的在第一象限的时候 X > 0 并未满足小于等于0 所以yaw是26° ,不需要加180°,写入角度26°也会转向26°位置
而第三象限的时候 X < 0 满足了小于等于0 所以 yaw = -26 °+ 180° = 154°,大家可以想象一下 154°是否为第三象限玩家所在位置度数
OK,现在大功告成,我们只需要获得自己头部位置和敌人头部位置,然后通过以上计算得出yaw和pitch,在通过写内存来达到自瞄头部,,我把简单过程写出来,具体函数我就不写了哈
角度计算函数:
vec3 aimbot::calcAngles(vec3 us,vec3 them)
{
vec3 dists;
dists =them - us;
float hyp = dists.magnitude();
vec3 result;
result.x = (asinf(dists.z / hyp)*57.295779513082f) ;
result.y = (atanf(dists.y / dists.x)*57.295779513082f);
result.z = 0;
if (dists.x <= 0)
{
result.y += 180;
}
result.x = -result.x;
return result;
}
大家可能会问为什么会有*57.295779513082f,这个是 180/3.1415926得到的,因为C++里asinf和atanf得出的弧度值,需要*(180/PI) 来转化为度数
void aimbot()
{
Player localPlayer = utils.getLocalPlayer();
Player closetPlayer = aim.getCloset();
closetPlayer.getInfo();
if (getClassid(closetPlayer.base) != 35)
return;
vec3 v2;
v2 = getBonePos(localPlayer.base);
vec3 v1;
v1 = getBonePos(closetPlayer.base);
vec3 aimat = aim.calcAngles(v2, v1);
int pViewAngle = vam.Read<int>(bEngine + clientState);
vam.Write<float>((pViewAngle + ViewAngles), aimat.x);
vam.Write<float>((pViewAngle + ViewAngles + 0x4), aimat.y);
}
aimat.x接受的是pitch,aimait.y接受的是yaw;其他的函数我就不发出来了哈,这里主要是介绍csgo自瞄中的数学,其他的大家可以自己去学习
if (getClassid(closetPlayer.base) != 35) 这句是判断玩家实体是否为玩家
vec3:
class vec3
{
public:
float x;
float y;
float z;
vec3() :x(0), y(0), z(0){}
vec3(float x,float y,float z):x(x),y(y),z(z){}
vec3 operator + (vec3 v)
{
vec3 vr;
vr.x = this->x + v.x;
vr.y = this->y + v.y;
vr.z = this->z + v.z;
return vr;
}
vec3 operator - (vec3 v)
{
vec3 vr;
vr.x = this->x - v.x;
vr.y = this->y - v.y;
vr.z = this->z - v.z;
return vr;
}
float magnitude()
{
return sqrt((x * x) + (y * y) + (z * z));
}
}
大家有什么不理解的可以在下面发粗来我给你们解答-.-+,只限本教程的哈 老哥有没有兴趣一起研究csgo,现在我在5E B5都有在玩,平滑自瞄还有点小缺陷,比较简陋。x_r 和y_r是最计算出来自瞄到敌人头的鼠标数值,x_r - 计算之前鼠标X的值 = 鼠标从准心移动到敌人的值 ,最后写x_r -鼠标从准心移动到敌人的值. 老哥怎么改进或者说有没有思路是不是有问题? 请问能教我求生之路怎么写自瞄外挂嘛 wgg666 发表于 2018-11-12 18:02
请问能教我求生之路怎么写自瞄外挂嘛
游戏外挂最好是从基础开始,你可以先去看看那些比较基础的 太厉害了 楼主,这个画坐标系的软件叫什么啊? xiaoyi279 发表于 2018-11-12 18:31
楼主,这个画坐标系的软件叫什么啊?
Sketchpad,不过这个是收费的,我也没买,我是试用20分钟慢慢画的。。。。。 自瞄可还行,学到了学到了!6666666666666666666666666666! 大佬就是大佬 为注册等了十年 发表于 2018-11-12 22:08
大佬就是大佬
其实就简单的三角函数问题。。。。仔细看一下很容易理解的 外挂还有这么复杂的数学原理,受教了