FPS 游戏实现GDI透视

Wesley13
• 阅读 722

FPS游戏可以说一直都比较热门,典型的代表有反恐精英,穿越火线,绝地求生等,基本上只要是FPS游戏都会有透视挂的存在,而透视挂还分为很多种类型,常见的有D3D透视,方框透视,还有一些比较高端的显卡透视,在透视实现难度上,方框透视是最复杂的一种,本教程将学习方框透视的实现算法,并编写通用辅助实现透视效果。

方框透视的原理是通过读取游戏中已知坐标数据,并使用一定算法将自己与敌人之间的距离计算出来,结合GDI绘图函数在窗体上直接绘制图形,直到现在这种外挂依然具有极强的生命力,原因就是其比较通用,算法固定并能够应用于大部分的FPS游戏中。

反恐精英下载地址:链接:https://pan.baidu.com/s/1U4-E9-xNIoHOyLg5aP_l7w 提取码:yupq
透视模块下载地址:链接: https://pan.baidu.com/s/1h-9CXW8yPggcgKtOUYAsiA 提取码: vg9v

寻找游戏坐标数据

教程中使用了【反恐精英:起源】这款经典FPS游戏作为演示对象,在开始编写方框算法之前我们需要获取一些坐标数据,这些数据是用于计算方框的基础,这里需要使用CE工具依次遍历找到 【FOV视场角】【本人坐标数据】【本人鼠标角度】【敌人坐标数据】【玩家数量】【玩家是否死亡】【敌人之间的数组偏移】接下来老司机将带大家把这些基址数据全部都找出来。滴滴滴 ~ 上车!!

找FOV视角: 视场角又称FOV,视场角的大小决定了摄像机的视野范围,简单来说FOV就是屏幕与摄像机之间的夹角,我们可以通过狙击枪的狙击镜来找到游戏的视场角度,当未开镜状态时搜索未知初始化数据(浮点数),开镜后搜索改变的数值(浮点数),依次遍历即可找到该游戏的视场角度,一般的FPS游戏视场角为90度的居多。

1.直接开找,打开CE和游戏,购买一把狙击枪,然后在CE中搜索【未知的初始值】,注意这里要选择浮点数搜索。这把枪是M700当年用这把枪打CF枪枪爆头很刺激,回想当年杀红眼的样子现在还记忆犹新。

FPS 游戏实现GDI透视

2.回到游戏,打开狙击枪的一倍狙击镜,在CE中搜索【变动的数值】,接着打开二倍狙击镜,继续搜索【变动的数值】,最后关闭狙击镜搜索【变动的数值】,该过程要重复10次左右。

FPS 游戏实现GDI透视

3.此时狙击镜处于关闭状态,直接搜索【未变动的数值】,然后拔出你的手枪,搜索【未变动的数值】因为手枪的视野与未开镜状态下的狙击枪是一样的,这样搜索能够尽量排除干扰,从而更精确的筛选到我们所需要的数据。

FPS 游戏实现GDI透视

4.经过了上方的遍历以后,结果已经不多了,我们可以猜测这个角度应该在【0-180度】之间,所以通过【介于两者之间】再次筛选一下结果,之后就可以看到有两个90度的角,而且是绿色的基址,一般情况下开发人员默认会将这个角设置为45,75或90度,这样会方便后期的编程,之间的偏差不会太大。

FPS 游戏实现GDI透视

5.回到游戏,右键手动调整狙击镜视野,发现下方地址栏中的数据也会发生变化,我们双击【242CDD34】这个内存地址,会发现这个基址是由【client.dll+2CDD34】模块加偏移得到的,至此我们已经知道了这款游戏的视场角是90度,而每次开镜【242CDD34】这个地址就会随之变化,从而确定该地址就是FOV。

FPS 游戏实现GDI透视

6.那我们该如何通过代码的方式读取到这个游戏当前的FOV数据呢?这里我通过易语言编写并封装了【透视模块】使用该模块将使透视辅助编写变得简单,后续的内容都会用到这个模块。

FPS 游戏实现GDI透视

找本人坐标数据: 通常情况下(X,Y)坐标的浮动较大不好定位,我们可以找Z坐标因为Z坐标控制人物的高低参数比较好找,首先搜索未知初始值(浮点数)然后跳到箱子上或走向更高的位置搜索增加的数值,回到地面上搜索减少的数值,重复这个过程最后就能找到Z轴的坐标,在游戏中(X,Y,Z)坐标是紧挨着的结构(+0,+4,+8) 找到了Z坐标相应的就可以计算出(X,Y)坐标。

1.打开CE并进入游戏,我们找一个比较平坦的地面,这里所使用的地图是de_dust2,然后使用CE直接搜索【未知的初始值】搜索类型为4字节即可。

FPS 游戏实现GDI透视

2.接着我们跳到第一个高点上,可以跳到箱子上或者是比当前的地面高一些的地方,然后搜索【增加的数值】结果如下。

FPS 游戏实现GDI透视

3.上方搜索完成以后,接着我们跳到第二个高点上,然后继续搜索【增加的数值】搜索结果如下。

FPS 游戏实现GDI透视

4.直接从箱子上跳到地面上,然后搜索【减少的数值】,搜索完成后不要动,直接在地面上搜索【未变动的数值】,这样循环不断的排查。

FPS 游戏实现GDI透视

5.经过不断的尝试与排查,我们已经找到了Z轴的坐标地址是【242CBE4C】,用上方的内存地址每次减去4,即可得到Y与X这两个坐标的内存地址。

FPS 游戏实现GDI透视

直接使用易语言配合透视模块,来读取坐标数据。

FPS 游戏实现GDI透视

找自己鼠标角度: 通常FPS游戏鼠标的准心Y坐标向上抬会减少,鼠标准心向下会增加,不断的遍历(浮点数)就可以搜索到鼠标的准心Y坐标,得到了鼠标的Y坐标之后然后+4就能得到鼠标的X的坐标参数。

1.打开CE进入游戏,将鼠标放置在屏幕的中心位置,直接搜索【未知初始化数据】(浮点数),然后将游戏鼠标向上微抬,回到CE搜索【减少的数值】多次向上抬并搜索减少的数值。

FPS 游戏实现GDI透视

2.接着将鼠标逐步向下微压,回到CE然后搜索【增加的数值】这里要重复十几次,最后不要动鼠标直接搜索【未变动的数值】即可找到以下结果,这里都是基地址选哪一个都可以。

FPS 游戏实现GDI透视

这里我们选择【242CDF9C】这个地址,然后在其基础上+4得到X坐标,通过使用易语言编程获取到这两个参数,代码如下所示:

FPS 游戏实现GDI透视

找单个敌人坐标数据: 首先在开始游戏之前通过控制台暂停对方阵营机器人的走动,使用bot_stop 1命令暂停,暂停后搜索未知初始值,然后使用bot_stop 0命令让机器人走两步后马上暂停,搜索变化的数值,开启机器人走动马上暂停,再次搜索变化的数值,不断尝试直到找到正确的数据,只要找到X轴的坐标,可以通过+4,+8的方式得到(Y,Z)的相对偏移。

1.首先开始一局游戏加入一个机器人(按下+号键添加),然后输入bot_stop 1命令让机器人暂停,在CE中搜索【未知初始数据】。

FPS 游戏实现GDI透视

2.输入 bot_stop 0 让机器人运动两步后马上暂停,然后CE中搜索【变动的数值】这个步骤需要重复多次,最终能够看到有几个非常像坐标的数据,下方的三个标红数据都可以,此处我就直接选择 1CBFFDD8 作为演示对象。

FPS 游戏实现GDI透视

3.将找到的内存地址加入到下方地址栏,然后我们右键选择【找出是什么改写了这个地址】,记下这个偏移数据([esi+15B8]),和基地址([1CBFE820])后期会用到。

FPS 游戏实现GDI透视

4.直接双击这个内存地址,然后可以看到 server_css.dll+3D24E4 模块地址+偏移地址,然后与15B8相加就能得到X轴的坐标数据。

FPS 游戏实现GDI透视

总结:在15B8的基础上每次递增+4既可得到Y轴与Z轴的坐标地址,最终可以用易语言编程获取单个敌人的坐标数据了。

FPS 游戏实现GDI透视

取当前玩家数量: 玩家数量的查找非常简单,大部分的FPS游戏都有人物统计菜单,按下TAB键则可看到,我们可以通过查看人物数量来查找,第一次搜索1,然后按下+号添加1个机器人搜索2,再次添加一个机器人搜索3,不断遍历即可得到玩家数量。

1.打开CE修改器,进入游戏后,按下TAB键即可看到当前只有自己,我们在CE中搜索1即可。

FPS 游戏实现GDI透视

2.按下大键盘下的+号,然后在CE中输入2点击【再次搜索】,以此循环,直至找到绿色的基址为止。

FPS 游戏实现GDI透视

总结:这个取玩家数量太简单了,自己找找就是,上方的绿色地址都可以作为判断依据,这里就直接使用 server_css.dll+3D24B8 这个地址了,易语言读取代码如下所示。

FPS 游戏实现GDI透视

判断敌人是否死亡: 取敌人的当前状态,在CS中我们可以搜索敌人的血量,首先添加1个机器人,然后搜索100,打敌人一枪(不要打头)搜索减少的数值,然后搜索未变动的数值,再次打敌人一枪搜索减少的数值,注意不要把敌人打死了就行,不断的遍历最后就能找到我们想要的敌人的血量,通过血量则可判断该地人似否死亡。

1.进入游戏手动添加一个机器人,此时机器人的血量是100,我们直接搜索精确数值100。

FPS 游戏实现GDI透视

2.用手枪打敌人的脚,不要打头!然后直接搜索【减少的数值】搜索完成以后,直接多次搜索【未变动的数值】重复2-3次即可找到为数不多的几个地址。

FPS 游戏实现GDI透视

上方找到了四个看似与血量相关的地址数据,我们分别将这几个数据改为100,发现当2CC7754C被改为100时其他的地址也跟着变成了100,说明第三个就是人物的血量。

3.接着在第三个地址处右键选择【找出是什么改写了这个地址】,可以看到偏移是【9c】,我们继续搜索 2CC774B0 这个内存地址。

FPS 游戏实现GDI透视

4.此时找到了基地址 server_css.dll+3D24E4 然后加上9C就是当前敌人的血量地址了。

FPS 游戏实现GDI透视

5.我们打死这个敌人,会发现血量变成了1说明这款游戏当人物死亡时,会用1来表示。

FPS 游戏实现GDI透视

总结:知道了这个特性,我们就可以用易语言来判断敌人是否死亡了哈,代码如下:

FPS 游戏实现GDI透视

找敌人之间的数组偏移: 在前面我们已经找到了第一个敌人的数据【server_css.dll+3D24E4】指向的就是第一个敌人的地址,通过与偏移【15B8】相加就能得到X坐标,在此基础上加4就能得到Y坐标,显然该游戏并不会将玩家数据放到偏移中,很有可能每个敌人分别占用一个地址,我们可以通过使用内存遍历工具,找到第二个敌人的地址,然后用第2个敌人的地址减去第1个敌人的地址就能得到敌人与敌人之间的差值。

1.首先进入游戏,添加两个机器人并将机器人暂停bot_stop 1,然后在CE工具的内存地址栏中,添加server_css.dll+3D24E4这个内存基址。

FPS 游戏实现GDI透视

2.接着用易语言编写一个乞丐版的基址遍历器,你也可以通过CE进行结构爬行,网上也有很多基址遍历工具可用,我这里为了方便就直接两行代码搞定,代码如下:

FPS 游戏实现GDI透视

3.游戏中保证只有两个机器人,然后运行这段代码,我们知道第一个地址003D24E4是第一个敌人的坐标数据,由于人物的内存矩阵中数据的排列不会偏差太大,这里我们主要找与6.231969801318e-012偏差不太大的内存来分析。

FPS 游戏实现GDI透视

上方结果中可知:地址003D24F4003D24E4浮点数的后缀相同且偏差不大,可以断定这两个就是两个敌人的基址,此时我们用 003D24F4 减去 003D24E4 等于 10 说明10就是敌人与敌人之间的偏移地址,不同的敌人与敌人之间相隔就是10,最后我们直接使用易语言获取到所有敌人的坐标数据:

FPS 游戏实现GDI透视

绘制屏幕方框与屏幕写字: 绘制外部方框就是调用了GDI绘图函数让其在指定的窗口句柄上绘图,我已经将绘制代码封装,直接调用就好这里就不罗嗦了。

FPS 游戏实现GDI透视

分别调用绘制方框与绘制文字,测试效果如下:

FPS 游戏实现GDI透视

方框透视算法分析

在前面的教程中我们已经手动找到了【FOV视场角】【本人坐标数据】【本人鼠标角度】【敌人坐标数据】【玩家数量】【玩家是否死亡】【敌人之间的数组偏移】这些基址数据,多数情况下类FPS游戏找坐标手法都大同小异,接下来我们将具体分析计算方框的思路,以及实现这些方框绘制算法。

第一象限求角: 假设敌人在第一象限,求鼠标指向与敌人之间的夹角b,可以使用反正切求导。

FPS 游戏实现GDI透视

我们知道自己与敌人的相对(X,Y)距离,可以使用反正切公式求出a角的度数。而我们最终的目的是要求出我们的鼠标指向与敌人之间的夹角b,此时我们可以通过已知的鼠标角度C减去a既可得到b的角度。

第二象限求角: 假设敌人在第二象限,而我们的鼠标依然指向在第一象限,求敌人与X轴之间的夹角度数。

FPS 游戏实现GDI透视

如上图:由于(X,Y)(黑色)是已知条件,我们可以通过X比Y求反正切,即可得到a角的度数,然后与90度相加,即可求出敌人当前坐标位置与X轴之间的夹角度数。

第三四象限: 敌人在第三与第四象限与上图差不多,最终目的就是求敌人的位置与X轴之间的夹角,第三象限应该加180度,第四象限加上270度数。这里就不罗嗦了,很简单的东西。

另外4种特殊情况: 如果敌人在第一象限且与X轴重合,那么敌人与X轴为之间的夹角度数必然为零度,同理如果与Y轴重合的话,那么X轴与敌人之间的夹角度数为90度,以此类推就是这四种特殊情况。

FPS 游戏实现GDI透视

上方的4条象限与特殊情况,如果展开的话一共是8种不同的情况,如下代码就是这八种不同情况,调试下面的这段代码会发现一个缺陷,那就是当我们绕着敌人转圈时,偶尔会出现一个大于180度的角度,这又是两种非常特殊的情况。

FPS 游戏实现GDI透视

特殊情况: 当敌人在第四象限且鼠标角度依然在指向第一象限的情况下,则会出现大于180度的角。

FPS 游戏实现GDI透视

如上图:我们的目标是求鼠标角度与敌人之间的夹角度数,而此时的鼠标指向第一象限,而敌人却在第四象限上,我们用360度减去e角度(e = 敌人坐标与x轴之间的夹角度数),即可得到K角度,用K角度加上M角度,即可得到鼠标与敌人之间的夹角度数,另一种特殊情况敌人与鼠标角度调换位置求角,最终代码如下:

FPS 游戏实现GDI透视

FOV视场角度: 摄像机的作用就是,移动游戏中的场景,并将其投影到二维平面,显示给玩家。

FPS 游戏实现GDI透视

如上图:摄像机与屏幕之间的夹角统称为视场角,游戏中的准星位置到屏幕的边缘是FOV的一半,以屏幕分辨率1024x768为例,当FOV为90度时,则准心与屏幕的垂线构成45度等腰直角三角形,此时的摄像机到屏幕的距离就是一半屏幕长度(1024/2 = 512)的大小。

三维横坐标转屏幕X坐标: 将三维矩阵中的敌人坐标数据,转换为屏幕的X坐标。

FPS 游戏实现GDI透视

如上图:我们需要求出敌人位置的坐标数据,可以使用 (x/y) x (1024/2) 最后还需要加上P的长度,由于窗口的总长度是1024那么我们可以直接除以2得到另一半的长度(512),将敌人位置与另一半长度相加就是敌人投射在屏幕上的X坐标,但是此时我们并不知道(X,Y)的长度,所以需要先求出(X,Y) 如下图所示。

FPS 游戏实现GDI透视

上图中:我们需要求出(X,Y)的距离,此时我们已经知道了M和C的长度,则此时我们可以直接使用勾股定理M的平方 + C的平方 (开方)= Z,得到Z之后,通过 sin a = (x/z) => sin a * z = X 此时我们已经得到的X的长度,接着 cos a =(y/z) => cos a * z = Y 此时我们也得到了Y的长度,最后 (x/y) x 512 + 512 即可得到敌人位置,投射到屏幕上的X坐标。

三维纵坐标转屏幕Y坐标: 三维横坐标搞懂了,这个纵坐标就更简单了,如下图:

FPS 游戏实现GDI透视

上图中:通过tan公式即可推导出d与c的距离,然后将d与c的长度相加,即可得到鼠标指向与敌人位置之间的距离,然后再加上屏幕高度的一半,本游戏屏幕高度为768,所以要加上384即可。

最终屏幕横坐标与纵坐标的转换算法如下所示,最后一点代码不搞了!要搬砖去了!

FPS 游戏实现GDI透视

最后的透视效果如下,此处游戏屏幕必须为1024x768,三维坐标转屏幕坐标算法中已经写死了,其他屏幕尺寸需要自行调整代码中的比值关系与相应数值。

FPS 游戏实现GDI透视

FPS 游戏实现GDI透视

 文章作者:lyshark

点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
CuterCorley CuterCorley
3年前
Python数据分析实战(2)使用Pandas进行数据分析
一、Pandas的使用1.Pandas介绍Pandas的主要应用包括:数据读取数据集成透视表数据聚合与分组运算分段统计数据可视化Pandas的使用很灵活,最重要的两个数据类型是DataFrame和Series。对DataFrame最直观的理解是把它当成一个Excel表格文件,如下:索引是从0开始的,也
Jacquelyn38 Jacquelyn38
2年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Easter79 Easter79
2年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Stella981 Stella981
2年前
Cocos Creator 3.0 入门 ! 2D 素材 3D 效果!
用2D素材实现3D效果!前言好久没写教程笔记了,不知大伙是否想念教程了?温馨提示:所有内容纯属个人瞎玩研究,如要上线项目,请自行评估~oh最近逛论坛,看到有一位小伙伴想实现下面这种透视效果。!(https://oscimg.oschina.net/oscnet/bb834e42888342aeb0658
Stella981 Stella981
2年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
2年前
2D实现背景图3D滚动效果(透视) !Cocos Creator !
\战斗地面效果!在2D中实现有纵深感(透视)的卷动效果。效果!(http://lamyoung.com//img/inpost/202006/2901.gif)回顾这次的纹理管理仍然是使用Sprite组件的渲染模式Mesh,需要的可以参考初探精灵中的网格渲染模式!(https://www.o
Wesley13 Wesley13
2年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
3个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这