吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 65719|回复: 274
收起左侧

[游戏安全] FPS网络游戏自动瞄准漏洞分析以及实现

    [复制链接]
头像被屏蔽
机智聪明的小迪 发表于 2019-2-8 21:47
0x0. 前言
来到论坛已经有一段时间了,目前大三学生,乐于分享知识,分享知识,不知道能不能申请精华。
新年刚刚过去,不知道大家亲戚走没走完,新的一年里,祝大家财源广进,身体健康,万事如意,一切都会好起来的!

0x1. 了解FPS游戏自瞄漏洞
经常玩游戏的朋友,应该知道FPS游戏,例如:穿越火线,逆战等等,他们的特点就是以第一人称视角进行操作人物,屏幕中间会有一个准星,通过准星瞄准敌人进行攻击以达到击杀效果和游戏体验。

由于FPS游戏的特殊游戏体验,所以使得很多不法分子利用逆向知识开发了很多自动瞄准的工具,破坏了游戏平衡。具体的原理如下:
1.找到存放鼠标准星的坐标基地址
2.找到人物数组基地址
3.找到人物数组下人物的相关属性偏移:血量,名字,坐标,阵营等
4.通过阵营判断是否为敌人,通过血量判断是否死亡,利用算法将自己的准星坐标修改为敌人所处的位置,实现自动瞄准

0x2. 利用某FPS网络游戏进行分析

用到工具:CE,OllyDbg

首先,我们分析了解一下FPS鼠标准星的知识,并且找出他的内存地址:

搜索前,我们要理清思路,那就是如何去定位鼠标的坐标,怎么定位比较方便。因为游戏分为鼠标X和鼠标Y两种坐标,鼠标X即左右的坐标,鼠标Y为上下坐标,由于左右坐标在游戏中转一圈无法确定坐标数据是否增大还是减小,所以我们通常分析鼠标的Y,即上下坐标。

针对鼠标Y坐标变动的情况分析:

无鼠标准星特殊加密:
1.向上移动准星坐标增大,向下移动准星坐标减小
2. 向上移动准星坐标减小,向下移动准星坐标增大

鼠标准星特殊加密:
鼠标准星上下无规律变动

对于没有鼠标准星特殊加密的游戏,我们通常在CE工具中搜索增加或者减少
对于存在 鼠标准星特殊加密的游戏,我们通常在CE工具中搜索变动或者未变动

另外,由于坐标等数据精度都是比较高的,所以我们通常搜索浮点数或者双浮点数

-----------------------------------------------------------------------------------------------------------------------------------------------------
                                                                                               ①开始分析鼠标坐标内存地址

我分析的游戏是创世战车,这是一款FPS射击网游,由于我已经提前逆向过,所以我们的CE操作顺序依次是:

附加进程->切换为搜索浮点数->搜索未知的初始值 ->鼠标向上搜索增加 ->鼠标向下搜索减少

然后 鼠标向上搜索增加 ->鼠标向下搜索减少重复循环过滤,最后我们剩下9个内存地址,通过修改得知:0x23E3588  是我们的鼠标Y内存地址

(, 下载次数: 7)
此时,我们已经得到了鼠标Y的内存地址,这个时候,我们不必去搜索鼠标X的内存地址,只需观察该地址相邻或者附近的地址值的变化即可得知鼠标X
因为鼠标XY坐标在游戏中存放是连续的,类似我们在上课写C语言结构体里面变量数据内存地址是连续的一样的道理

那么如何查看相邻地址内存呢?CE有个自带的功能:
(, 下载次数: 5)


按照图示的标注的顺序,在下面的窗口编辑框内填入相关地址:

(, 下载次数: 6)
在这里解释一下为什么我们需要填入23E3500,因为鼠标Y地址是: 23E3588,鼠标X在附近的位置,所以我们存在一个取值范围,这个范围不是很大,所以我们填入了一个估值,填入后定义结构体,一切回车默认即可。

通过观察和修改,我们发现当修改23E3584这个地址时,鼠标的X准星会变动,由此我们得知了该游戏的鼠标坐标内存地址,即:

鼠标X:Crossout.exe+1963584
鼠标Y:Crossout.exe+1963588(该游戏基地址存放是以模块名+模块偏移存放的)

(, 下载次数: 7)

(, 下载次数: 7)

至此,我们的鼠标坐标内存地址分析完毕,当然了,分析这个还不够,下面我们来分析一下人物数组及其结构:

-----------------------------------------------------------------------------------------------------------------------------------------------------
                                                                                               ②开始分析人物数组

说到人物数组,我们必须要了解一下游戏中人物对象的存放形式,一般均为数组, 优点:

1、按照索引查询元素速度快
2、能存储大量数据
3、按照索引遍历数组方便

而且这也是我们C/C++语言中常用的写法

那么我们来分析一下该游戏,由于该游戏没有子弹数量,所以我们可以通过血量来分析该游戏的数据:

由于血量精度也比较高,所以存放形式也多为浮点数或者双浮点数,由于精度过高,所以我们不能够搜索精确数值,改为搜索两者之间的数值:

(, 下载次数: 6)
通过撞击建筑物或者其他车辆,使自身血量变动,然后过滤到血量地址:

(, 下载次数: 4)

这个时候,我们需要用到另外一款调试器:OllyDbg

我们附加进程,使用dd指令,查看血量地址,然后下硬件断点,寻找数组和基地址

(, 下载次数: 8)

程序断在了0x011299D9位置处,观察寄存器,我们得知eax为人物的临时对象地址,0x0C0为我们的血量地址偏移:0x39EE8FF0 + 0x0c0 = 0x39EE90B0 (eax)

(, 下载次数: 7)

所以我们继续去追eax,通过单步call,我们发现eax实际上来源于上方的Call的返回值:

(, 下载次数: 3)

(, 下载次数: 6)

我们进入Call去追踪Eax来源,通过追踪我们发现了数组:

(, 下载次数: 6)

并且我们发现了数组的基地址:

(, 下载次数: 4)
关于最终数组的地址的寻址过程,在这里不再赘述,我只放出大概的OD逆向的注释,大家对照一下就可以了:

(, 下载次数: 6)

(, 下载次数: 6)

(, 下载次数: 4)

最终通过我们的分析得到数组的表达式:

dd   [[1C6E1F0]+(([[23E20D4]*7c0+2BE8+23CFD80]&0FFF)+2aad)*c]+0c0

其中,通过我们的分析,得知:0x23E20D4这个地址存放的使我们自身的数组的下标,所以,表达式可转换为

dd   [[1C6E1F0]+(( n*7c0 + 2BE8 + 23CFD80 ]&0FFF)+2aad)*c]+0c0   n为下标

分析完数组之后,我们接下来就来分析人物的结构了!

-----------------------------------------------------------------------------------------------------------------------------------------------------
                                                                                              ③开始分析人物结构

由于人物结构是一个结构体,该结构体的起始地址为人物对象地址,所以,我们继续用CE的结构体分析工具去分析人物对象地址,也就是刚才的eax地址:

通过观察,我们立刻就得到了人物名称的偏移量:0x68

(, 下载次数: 5)

通过观察和修改浮点数,我们观察到了人物坐标的偏移量:

人物左右X:0x2B0
人物前后Y:0x2B8
人物高度Z:0x2B4(个人习惯这个为Z)

(, 下载次数: 3)
由此,我们可以总结几个表达式了!!!


dd [[1C6E1F0]+(([n*7c0+2BE8+23CFD80]&0FFF)+2aad)*c]+0c0  人物血量

dd [[1C6E1F0]+(([n*7c0+2BE8+23CFD80]&0FFF)+2aad)*c]+068  人物名称

dd [[1C6E1F0]+(([n*7c0+2BE8+23CFD80]&0FFF)+2aad)*c]+02B0  人物X坐标

dd [[1C6E1F0]+(([n*7c0+2BE8+23CFD80]&0FFF)+2aad)*c]+02B8  人物Y坐标

dd [[1C6E1F0]+(([n*7c0+2BE8+23CFD80]&0FFF)+2aad)*c]+02B4  人物Z坐标

然后,我们就可以去游戏写个遍历器看一下了!走!去写遍历器!

-----------------------------------------------------------------------------------------------------------------------------------------------------
                                                                                             ④写遍历器查看游戏数据


大致逻辑如下,可能我的代码功底不是很好,让大家见笑啦~

因为该游戏房间人数最多为32人,所以我们for循环的次数为i<32

[C++] 纯文本查看 复制代码
//定义遍历Address
DWORD TempAddress, RetTemp, GetBase, ObjectAddress, ObjectValue;
 
//基地址
DWORD BaseAddress = GetProcessBaseAddress(ProcessId) + BasePtr;
 
//数组基地址
DWORD Address_Array = GetProcessBaseAddress(ProcessId) + ArrayPtr;
 
char* Name = NULL;
int Count = 1;
 
 
 
for (int i = 0; i < 32 ; i++)
{
//地址解密
TempAddress = i * 0x7c0 + Address_Array + 0x2BE8;
 
RetTemp = _ReadMemeryInt(_hGameHandle, TempAddress);
 
//计算数组遍历地址
RetTemp = ((RetTemp & 0x0fff) + 0x2AAD) * 0x0c;
 
//基地址
GetBase = _ReadMemeryInt(_hGameHandle, BaseAddress);
 
//计算人物对象地址
ObjectAddress = GetBase + RetTemp;
 
 
//读人物对象地址
ObjectValue = _ReadMemeryInt(_hGameHandle, ObjectAddress);
 
//判断对象是否存在
if (ObjectValue != NULL)
{
 
//读取人物血量
float Bloat = _ReadMemeryFloat(_hGameHandle, ObjectValue + 0xc0);
//读取人物名称
Name = _ReadMemeryString(_hGameHandle, ObjectValue + 0x68);
 
 
printf("第%d个人:   数组下标:%d   人物名称:%s     对象地址:%x   血量:%.3f\n",Count, i,Name, ObjectValue, Bloat);
 
ObjectAddress = NULL;
ObjectValue = NULL;
 
Count += 1;
}
}


游戏中的效果,我们遍历到了敌人的数据,比如重要的下标数据和对象地址:

(, 下载次数: 2)

-----------------------------------------------------------------------------------------------------------------------------------------------------
                                                                                             ⑤分析自瞄朝向

我们所有的数据基本上都分析完了,下面我们来分析一下网游自动瞄准的算法吧,在这里,我推荐大家用生活和游戏相结合的方式
也就是游戏和生活联系在一起。

古代的时候,对于我们生活的地球,人们会讲“天圆地方”这么一个概念

那么我们可以借鉴一下,把游戏中的地图看成方的,把我们看做坐标原点,然后建立一个直角坐标系,并且标注上北下南,左西右东:

(, 下载次数: 4)

然后我们先得知一个规律:

1.如果我们修正鼠标X和鼠标Y为0,那么游戏准星将指向一个东南西北的正方向
2.前后移动如果人物X坐标未变动或者变动幅度小,则我们处在坐标系Y方向
3. 前后移动如果人物Y坐标未变动或者变动幅度小,则我们处在坐标系X方向

通过规律,然后通过观察,发现人物前后走动时,Y坐标变化剧烈,说明:

1.我们小车在Y轴方向上
2.又因为向前减少,向后增加,说明我们的小车:坐北朝南,鼠标的位置此时指向了南方

(, 下载次数: 3)

那么这个时候,我们把方向分析完了,我们来分析一下,鼠标坐标的变化规律:

我们此时是指向南方的,我们从南向北顺时针旋转鼠标,观察鼠标规律:

鼠标从南向北: 鼠标值的变化大致为:0--π

(, 下载次数: 2)

继续旋转:-π  此时π和-π的位置,也就是正北方,我们发现是重合的

(, 下载次数: 3)
由此,根据游戏中的变化规律,我们可以作图:(鼠标的度数和象限和东西南北的关系)

(, 下载次数: 6)

这个时候,可能有的朋友会疑问了,画这个有什么用???

客观,且听我细细分说:

1.我们刚开始假想自己在坐标原点的位置
2.我们通过1得到了不同象限内鼠标角度的范围

那么,我们只需要知道敌人位于哪个象限就可以确定鼠标角度的范围,并且可以精确计算鼠标角度了

所以,我们应该怎么确认敌人在哪个象限呢?

解:

既然游戏为一个直角坐标系,我们位于坐标原点,因此:

1.当敌人X>自身X  敌人Y>自身Y   敌人位于第一象限
2. 当敌人X<自身X  敌人Y>自身Y   敌人位于第二象限
3. 当敌人X<自身X  敌人Y<自身Y   敌人位于第三象限
4. 当敌人X>自身X  敌人Y<自身Y   敌人位于第三象限

上面大家唯一要注意的就是正负的大小,不要搞混!

-----------------------------------------------------------------------------------------------------------------------------------------------------
                                                                                           ⑥分析自瞄的鼠标X坐标

因为我们得知了鼠标的变化规律,也得知了象限的变化,所以,我们只需要把我们和敌人的角度算出来就可以了!
那么应该怎么计算呢?

且听我细细分说!还是刚才的图:

我们以我们为起点,以敌人的坐标为终点,不考虑Z坐标,进行作图,连线,构造三角形!

那么根据几何知识,我们得知绿色的地方即为我们需要瞄准的度数,也就是我们要修改的鼠标的X角度

(, 下载次数: 5)
那么应该如何计算呢?

我想聪明人已经想到了:那就是用反正切

我们已知敌人的Y,知道我们的Y,那么

敌人Y - 我们Y = 三角形的对边
敌人X - 我们X = 三角形的临边

利用反正切,对边/临边,得知自瞄X的角度,由于C语言中提供了函数atan2,因此,我们直接用atan2函数即可,atan2函数释义如下:

C 语言里 double atan2(double y,double x) 返回的是原点至点(x,y)的方位角,即与 x 轴的夹角。也可以理解为复数 x+yi 的辐角。返回值的单位为弧度
因此,第一象限初步的角度公式为:

atan2((敌人Y-我们Y),(敌人X-我们X)),由于该角度取值范围为[0,π/2],从北到东为π/2--0,变化规律为:逐渐减小

也就是说,我们生活中来看,从北到东顺时针为,逐渐减少,但是游戏中变化为:-π->π/2,逐渐增大

所以,继续敲黑板:把生活中的转化为游戏中的,那么我们直接加个负号: atan2((敌人Y-我们Y),(敌人X-我们X))就逐渐增大了

又因为加负号后的生活中取值变化为:-π/2->0  游戏中为: -π->π/2,所以依然需要在原公式的基础上-π/2

那么最终的第一象限的算法也就是:- atan2((敌人Y-我们Y),(敌人X-我们X)) - π/2

以此类推,全部象限的鼠标X算法大致如下:
[C++] 纯文本查看 复制代码
        /*
计算水平横角度
*/
FLOAT AimbotAngle_X;
if (X_Target > X_MyPlayer && Y_Target > 人物.fY)//第一象限
{
AimbotAngle_X = (FLOAT)(0 - atan2(Y_Target - 人物.fY, X_Target - X_MyPlayer) - 3.1415926 / 2);
}
if (X_Target < X_MyPlayer && Y_Target > 人物.fY)//第二象限
{
AimbotAngle_X = (FLOAT)(atan2(Y_Target - 人物.fY, X_MyPlayer - X_Target) + 3.1415926 / 2);
}
if (X_Target < X_MyPlayer && Y_Target < 人物.fY)//第三象限
{
AimbotAngle_X = (FLOAT)(3.1415926 / 2 - atan2(人物.fY - Y_Target, X_MyPlayer - X_Target));
}
if (X_Target > X_MyPlayer && Y_Target < 人物.fY)//第四象限
{
AimbotAngle_X = (FLOAT)(atan2(人物.fY - Y_Target, X_Target - X_MyPlayer) - 3.1415926 / 2);
}


至此,我们分析完了鼠标的X横角度,那么我们带着愉悦的心情继续分析鼠标的Y角度吧!

-----------------------------------------------------------------------------------------------------------------------------------------------------
                                                                                            ⑥分析自瞄的鼠标Y坐标


自瞄的Y坐标相对简单,用一张图大家就明白了:

(, 下载次数: 4)

依然,绿色标注的角度为我们的瞄准的Y角度,那么如何计算呢,这一次需要用到勾股定理:

首先我们把上面三角形的临边计算出来:也就是X的平方 + Y的平方 ,然后开平方,我们把这个值设为P

得知了P,得知Z = 敌人的Z-我们的Z,那么我们就可以计算角度了:atan2(Z,P),取值范围为0--π/2  逐渐增大

那么游戏中的变化规律呢,我们看一下:

当鼠标Y为0时,朝向中心位置:

(, 下载次数: 4)

当鼠标向最上方时,大致值为π/2:

(, 下载次数: 3)
当鼠标向最下方时,大致值为-π/2:

(, 下载次数: 2)

那么也就是说如果敌人Z高于我们Z,那么游戏角度处于0--->π/2,生活中角度也为:0-π/2,无需转换

如果敌人Z小于我们Z,游戏角度为:0- -π/2,生活中角度要进行取反,也就是 -atan2(Z,P)

注意此时的Z,也进行了变化,因为我们位于坐标原点,为保证值为正数  所以Z = 我们Z - 敌人Z

所以最终横角度大致代码如下:

[C++] 纯文本查看 复制代码
         /*
        计算上下俯仰角
        */
FLOAT AimbotAngle_Y;
FLOAT Distance;
 
Distance = sqrt((X_Target - X_MyPlayer)*(X_Target - X_MyPlayer) + (Y_Target - Y_MyPlayer)*(Y_Target - Y_MyPlayer));
 
//敌人高度 > 自己高度
if (Z_Target > Z_MyPlayer)
{
AimbotAngle_Y = atan2(Z_Target - Z_MyPlayer, Distance);
}
 
//敌人高度 < 自己高度
if (Z_Target < Z_MyPlayer)
{
AimbotAngle_Y = 0 - atan2(Z_MyPlayer - Z_Target, Distance);
}
 
 


最终,我们的算法就结束了,还差最后一步,那就是源源不断的写入敌人的角度数据到我们的鼠标角度中,就可以实现锁定敌人的功能

另外还需要注意一点,该游戏在分析阵营时,在人物结构下未发现阵营数据,通过观察,得知阵营在数组地址 减去 0x38的位置

任意人物的阵营:数组下标*7C0+Crossout.exe+194FD80+2BE8 - 0x38    敌方跟我方的阵营是不同的

我们现在已经做完了几乎全部的铺垫,大致的逻辑如下:

[C++] 纯文本查看 复制代码
自瞄()
{
       得出人物信息()
      {
           得到自己的属性:坐标XYZ 血量  阵营  是否死亡  鼠标角度;
           得到其他人的属性:坐标XYZ 血量  阵营  是否死亡
     }
    计算角度坐标
    瞄准()
   {
    判断死亡  是否在房间
    判断阵营
    选择最近的敌人瞄准   10米  100米  威胁最大的
   }
}



再总结一下:

任意人物的阵营:数组下标*7C0+Crossout.exe+194FD80+2BE8 - 0x38    敌方跟我方的阵营是不同的

人物血量 : [[1C6E1F0]+(([n*7c0+2BE8+23CFD80]&0FFF)+2aad)*c]+0c0   通过判断敌人血量可以确定敌人是否死亡

人物名称 :[[1C6E1F0]+(([n*7c0+2BE8+23CFD80]&0FFF)+2aad)*c]+068

人物X坐标 :[[1C6E1F0]+(([n*7c0+2BE8+23CFD80]&0FFF)+2aad)*c]+02B0

人物Y坐标 :[[1C6E1F0]+(([n*7c0+2BE8+23CFD80]&0FFF)+2aad)*c]+02B8

人物Z坐标 :[[1C6E1F0]+(([n*7c0+2BE8+23CFD80]&0FFF)+2aad)*c]+02B4

人物对象地址:[0143e1f0]+(([01B9FD80+0*07c0+2BE8]&0FFF)+2AAD)*0c    通过判断对象地址值是否有效可以判断是否在房间内


那么,通过这些数据,我们就可以知道FPS游戏自瞄漏洞的利用方式了。

-----------------------------------------------------------------------------------------------------------------------------------------------------
                                                                                           ⑦修改内存实现自瞄

[C++] 纯文本查看 复制代码
大致代码如下,由于我做了些封装,所以,大家明白写法逻辑就可以了:
 
//写自瞄X
WriteMemeryFloat(_hGameHandle, GetProcessBaseAddress(ProcessId) + MouseX, 水平角);
//写自瞄Y
WriteMemeryFloat(_hGameHandle, GetProcessBaseAddress(ProcessId) + MouseY, 俯视角);
 
//写内存小数型
BOOL WriteMemeryFloat(HANDLE hGameHandle, DWORD _address, FLOAT Data)
{
return WriteProcessMemory(hGameHandle, LPVOID(_address), &Data, sizeof(Data), NULL);
}
 
由于该游戏的地址以模块地址 + 模块偏移形式存放,所以,我封装了获取本模块基地址的函数:
 
//取本程序模块地址
DWORD_PTR GetProcessBaseAddress(DWORD processID)
{
DWORD_PTR   baseAddress = 0;
HANDLE      processHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processID);
HMODULE     *moduleArray;
LPBYTE      moduleArrayBytes;
DWORD       bytesRequired;
 
if (processHandle)
{
if (EnumProcessModules(processHandle, NULL, 0, &bytesRequired))
{
if (bytesRequired)
{
moduleArrayBytes = (LPBYTE)LocalAlloc(LPTR, bytesRequired);
 
if (moduleArrayBytes)
{
unsigned int moduleCount;
 
moduleCount = bytesRequired / sizeof(HMODULE);
moduleArray = (HMODULE *)moduleArrayBytes;
 
if (EnumProcessModules(processHandle, moduleArray, bytesRequired, &bytesRequired))
{
baseAddress = (DWORD_PTR)moduleArray[0];
}
LocalFree(moduleArrayBytes);
}
}
}
CloseHandle(processHandle);
}
return baseAddress;
}

0x3. 总结

至此,FPS游戏自瞄游戏漏洞分析完成

全部FPS游戏均存在内存自动瞄准的漏洞,在这里,并不是希望大家去破坏游戏,而是我希望大家能够知道原理,学到知识,希望大家不要做破坏游戏平衡的事情.

写完了,不知道大家喜不喜欢,如果喜欢的话,我会抽出时间写一下方框透视的绘制和算法

不知道管理能不能加精,另外今年也打算读研究生了

不打广告,不留名,希望大家好好学习,新的一年里,更上一层楼!

免费评分

参与人数 246吾爱币 +250 热心值 +220 收起 理由
朝辞白帝 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
righter + 1 + 1 我很赞同!
Vicar5235 + 1 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
油桶 + 1 + 1 用心讨论,共获提升!
15048048021 + 1 + 1 用心讨论,共获提升!
Light紫星 + 1 + 1 我很赞同!
jpm822phgr2 + 1 + 1 用心讨论,共获提升!
aimabihan + 1 + 1 谢谢@Thanks!
Orekize + 1 + 1 谢谢@Thanks!
newcools521 + 1 我很赞同!
Shaiem + 1 + 1 用心讨论,共获提升!
清辞。 + 1 用心讨论,共获提升!
candlce + 1 + 1 鼓励转贴优秀软件安全工具和文档!
bing1999 + 1 + 1 谢谢@Thanks!
1008601 + 1 + 1 我很赞同!
独饮悲~ + 1 + 1 感谢您的宝贵建议,我们会努力争取做得更好!
JuDei + 1 + 1 用心讨论,共获提升!
XiroNeko + 1 + 1 热心回复!
乐乐同学 + 1 热心回复!
墨月与墨鱼 + 1 + 1 我很赞同!
爱拍阴天 + 1 + 1 我很赞同!
slaap + 1 + 1 用心讨论,共获提升!
gm0515 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
鹅妹子嘤 + 1 + 1 用心讨论,共获提升!
我吾爱破解账号 + 1 + 1 我很赞同!
Mr.Eleven + 1 谢谢@Thanks!
楚辞辞 + 1 + 1 用心讨论,共获提升!
简单单单 + 1 + 1 用心讨论,共获提升!
孙嘉隆 + 1 谢谢@Thanks!
justlll + 1 谢谢@Thanks!
a321852123 + 1 + 1 太神拉~
问题不大 + 1 + 1 鼓励转贴优秀软件安全工具和文档!
11ewww + 1 + 1 用心讨论,共获提升!
DaveiH + 1 + 1 谢谢@Thanks!
zhs_poison + 1 + 1 我很赞同!
未来与世界 + 1 + 1 热心回复!
传火薪王古达子 + 1 + 1 我很赞同!
yyyl + 1 + 1 用心讨论,共获提升!
xiecong1998 + 1 用心讨论,共获提升!
_conceited + 1 我很赞同!
WA自动机 + 1 用心讨论,共获提升!
逆光灬流火 + 1 + 1 谢谢@Thanks!
那真的牛批 + 1 + 1 用心讨论,共获提升!
七度空间 + 1 + 1 真的厉害,小白也能稍微懂一点了,谢谢
Sm1Lin9Fac3 + 1 + 1 我很赞同!
三宅的猫子 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
lc2zyq + 1 + 1 我很赞同!
琢钰 + 1 + 1 用心讨论,共获提升!
Diablita + 1 我很赞同!学习了,再也不玩CF. CS
NameQuin + 1 我很赞同!
ffqaq + 1 + 1 我很赞同!
rain21 + 1 + 1 我很赞同!
RoB1n_Ho0d + 1 + 1 热心回复!
G31001 + 1 + 1 我很赞同!
极品菜雀 + 1 + 1 厉害了!
q56535 + 1 我很赞同!
cenglou + 1 + 1 我很赞同!
zzzz7777cl + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
tdher987 + 1 + 1 用心讨论,共获提升!
gongyong728125 + 1 + 1 热心回复!
newpowersky + 1 + 1 我很赞同!
zhizhoushen + 1 + 1 谢谢@Thanks!
shixinlan + 1 + 1 用心讨论,共获提升!
doidt + 1 + 1 谢谢 加油加油!!!
cnzmg + 1 用心讨论,共获提升!
月社琉璃 + 1 我很赞同!
super鲁校长 + 1 + 1 谢谢@Thanks!
BK2011111 + 1 热心回复!
qq499216557 + 1 + 1 用心讨论,共获提升!
CrazyNut + 3 + 1 膜拜大佬
1188 + 1 + 1 勾股定理都出来了
T316huanghe + 1 我很赞同!
破天丿彡 + 1 大写 懵逼在脸上
arwel1912 + 1 用心讨论,共获提升!
Most苏 + 1 + 1 用心讨论,共获提升!
qaz003 + 1 + 1 超赞,理论实践都普及了……。
西西里公爵 + 1 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
阿吉小家伙 + 1 + 1 我很赞同!
Hansenne + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
乎乎 + 1 + 1 膜拜大神
bb8820 + 1 谢谢@Thanks!
行者小波 + 1 用心讨论,共获提升!
傻乎乎的小白 + 1 + 1 热心回复!
吾爱丶抹杀 + 1 + 1 鼓励转贴优秀软件安全工具和文档!
593365053 + 1 + 1 用心讨论,共获提升!
qwer1193 + 1 + 1 谢谢@Thanks!
gorden + 1 + 1 热心回复!
′小手冰凉 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
panglihuan + 1 + 1 我很赞同!
流年随心荏苒 + 1 + 1 用心讨论,共获提升!
DcHeathen + 1 + 1 用心讨论,共获提升!
poisonbcat + 1 用心讨论,共获提升!
FFFGGL + 1 + 1 用心讨论,共获提升!
chinabilibili + 1 + 1 谢谢@Thanks!
SakuyaPrs + 1 + 1 热心回复!
小泡泡_ + 1 + 1 谢谢@Thanks!
瓜子吧3 + 3 + 1 我很赞同!
Minesa + 1 + 1 我很赞同!
sunzhiyang + 1 + 1 热心回复!
sunhaipeng1997 + 1 用心讨论,共获提升!

查看全部评分

本帖被以下淘专辑推荐:

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

smile1110 发表于 2019-2-9 20:47
本帖最后由 smile1110 于 2019-2-9 20:48 编辑

这篇帖子写的真棒啊,尤其是这个视角转换,不过并不需要如此麻烦,直接调整到 4:3的分辨率 系统鼠标调整到6 这时候从枪口 或者炮口出去的这条线,开始计算 角速度和线速度 ,只要子弹沿着这条线出去,就一定会击中目标,若是还有一些类似后座力什么的随机的话,可以加入椭圆曲线的离散范围取值,而并不需要把立体变为立方体 通过这个缩放标量 ,更不需要计算三角函数或者相似三角形 这些 解析几何




免费评分

参与人数 4吾爱币 +3 热心值 +4 收起 理由
zhukai055 + 1 你写的也特别棒,但G一般都是内存精准移动,通过计算鼠标恐怕有误差。
小小少年烦恼多 + 1 + 1 大佬讲解的很清楚,就自动瞄准而言,差不多懂了,那么对于过检测呢,想了解
NOWorEVER + 1 + 1 用心讨论,共获提升!
Atreusman + 1 + 1 我很赞同!

查看全部评分

wuzeqiao 发表于 2019-2-8 23:09
我是咕噜 发表于 2019-2-8 21:51
565266718 发表于 2019-2-8 21:58
先支持楼主。。其次图片全挂。。
S.K 发表于 2019-2-8 21:58
图片都是直接贴过来的,看不了。。。。
zqguang3708 发表于 2019-2-8 22:05
姐姐图片没了   更新一下啊
头像被屏蔽
 楼主| 机智聪明的小迪 发表于 2019-2-8 22:12
图片已经恢复了,之前我写在word的,想着顺便复制过来,没想到直接全挂了
zzz995 发表于 2019-2-8 22:15
图片有啊 是你们的网络问题吧
az216115 发表于 2019-2-8 22:29
哇哦,我也要考研究生了啊啊啊啊啊,小姐姐分析的很到位
121890575 发表于 2019-2-8 22:41
学习了,辛苦了。
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-4-19 20:35

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表