FPS游戏通用准星修正实现自瞄_自瞄的瞄准角度是什么-程序员宅基地

技术标签: 那些年我们玩过的网游  

FPS游戏内的十字瞄准视角其实就是一个视角摄像机这个应该不难理解吧,如何调整摄像机的视角就要用到一个叫“姿态角(Euler角)”的数据,即: yaw , pitch , roll。这3个值的解释如下:

pitch是围绕X轴旋转,也叫做俯仰角
yaw是围绕Y轴旋转,也叫偏航角
roll是围绕Z轴旋转,也叫翻滚角

用张图来解释比较直观:


首先我们要先知道自己的Euler角值,然后就要知道目标的坐标,最后通过公式计算出需要修正的Euler角值。

下面直接给出封装好的运算函数:

#define M_PI		3.14159265358979323846
#define M_PI_F		((float)(M_PI))
#define DEF_AIMBOT_FOV	15.0f
#define DEG2RAD(x)  ( (float)(x) * (float)(M_PI_F / 180.f) )
#define RAD2DEG(x)  ( (float)(x) * (float)(180.f / M_PI_F) )


#pragma pack(push)
#pragma pack(1)

typedef struct tag_Rotator{
	float  Pitch;                                                 
	float  Yaw;  
	float  Roll;
}TROTATOR, *PROTATOR;

typedef struct tag_Vector3 {
	float x;
	float y;
	float z;
}TVECTOR3,*PVECTOR3;

#pragma pack(pop)


TROTATOR Vec2Rot(PVECTOR3 vec)
{
	TROTATOR rot;
	rot.Yaw = RAD2DEG(std::atan2f(vec->y, vec->x));
	rot.Pitch = RAD2DEG(std::atan2f(vec->z, std::sqrtf(vec->x * vec->x + vec->y * vec->y)));
	rot.Roll = 0.f;
	return rot;
}

TROTATOR Clamp(TROTATOR r){
	if (r.Yaw > 180.f)
		r.Yaw -= 360.f;
	else if (r.Yaw < -180.f)
		r.Yaw += 360.f;

	if (r.Pitch > 180.f)
		r.Pitch -= 360.f;
	else if (r.Pitch < -180.f)
		r.Pitch += 360.f;

	if (r.Pitch < -89.f)
		r.Pitch = -89.f;
	else if (r.Pitch > 89.f)
		r.Pitch = 89.f;

	r.Roll = 0.f;
	return r;
}

//参数 目标坐标,自己的坐标,自己视角
TROTATOR CalcAimToTarget(PVECTOR3 pTarPos, PVECTOR3 pLocPos, PROTATOR pLocRot){
	TVECTOR3 delta = { 0 };
	delta.x = pTarPos->x - pLocPos->x;
	delta.y = pTarPos->y - pLocPos->y;
	delta.z = pTarPos->z - pLocPos->z;
	TROTATOR ideal = Clamp(Vec2Rot(&delta));
	ideal.Pitch = ideal.Pitch - pLocRot->Pitch;
	ideal.Roll = ideal.Roll - pLocRot->Roll;
	ideal.Yaw = ideal.Yaw - pLocRot->Yaw;
	//计算出目标所需要的视角范围
	FLOAT angFOV = sqrt(angDelta.Pitch * angDelta.Pitch + angDelta.Roll * angDelta.Roll + angDelta.Yaw * angDelta.Yaw);
	//游戏中大部分玩家的FOV都是80~90这个值可用于判断视野范围内
	/*
		if (angFOV < DEF_AIMBOT_FOV){
			OOXX
		}
	*/
	//修正值
	return Clamp(ideal);
}

最后将计算结果加上自己的 Euler角值即可将准星修正到你需要的位置。

PS. 一般套路FPS模型都会有个人物骨骼列表,里面包含了模型所有关键部位的坐标。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/yoie01/article/details/79225085

智能推荐

恩智浦半导体推出近距离非接触式读卡器IC CLRC663_clrc663 demo-程序员宅基地

文章浏览阅读2k次。原文地址::http://www.elecfans.com/xinpian/ic/CLRC663.html相关文章1、CLRC663 High Performance NFC Reader Solution----http://www.bdtic.com/NXP/CLRC663.html2、RFID 评估和开发套件及电路板----http://www.digikey.cn/pr_clrc663 demo

lease 分布式_存储覆盖写和追加写-程序员宅基地

文章浏览阅读917次。背景和介绍缓存是计算机里广泛使用的一种技术,对降低读取延迟、网络流量和服务器负载都非常有效,但也带来了一致性(Consistency)的问题。所谓一致就是客户端总能读到最新的数据,使用缓存后有可能服务器端的数据已经被修改,但客户端仍然从缓存中读取陈旧的数据。为了保证一致性,有两种常见的解决办法,第一种是轮询(Polling),即每次读取数据时都先询问服务器数据是不是最新的,如果不是就从_存储覆盖写和追加写

java.lang.ClassCastException: java.math.BigDecimal cannot be cast to java.lang.Double-程序员宅基地

文章浏览阅读5.8k次,点赞2次,收藏2次。报错:java.lang.ClassCastException: java.math.BigDecimal cannot be cast to java.lang.Double原因:类型转换异常,这里要从map里面取出坐标点然后存起来,直接强转然后就报了错,网上查出来说是数据超长没办法直接强转,不知道原因对不对LatLng latLng = new LatLng((Double) aoLatLng.get("lng"), (Double) aoLatLng.get("lat"));解决办法:先toS_java.lang.classcastexception: java.math.bigdecimal cannot be cast to java.la

uniapp 项目双屏异显插件使用方式_uniapp分屏-程序员宅基地

文章浏览阅读4k次。本文主要记录uniapp双屏异显插件(安卓收银机双屏(副屏)异显,主副屏通讯)使用方式:在uniapp中安装和引入插件请参考uniapp文档,这里不作介绍uniapp里面调用调用也是参考插件文档进行的,直接贴源码吧!页面挂在成功后调用插件进行副屏显示 页面中的输入框和发送按钮模拟信息处理 send方法负责发送信息到副屏 /static/dist/index.html为打包的vue项目地址<template> <view> <input.._uniapp分屏

IIS真正能用的ISAPI-Rewrite防盗链规则写法-程序员宅基地

文章浏览阅读92次。本规则支持白名单排除式防盗链,搜索引擎友好不屏蔽,被盗链后的错误提示转向,支持各种文件类型,经作者亲验真的能用,第一时间在原创发表,请继续往下阅读。近来小站遇到了盗链问题,至使网站的流量枉费流失,于是被迫准备为服务器安装防盗链机制以挽救本就不宽裕的带宽。通过G.CN和B.CN搜索后得出了几种不同的方案,例如网站程序的URL伪装法、服务器端的收费插件法和ISAPI-R..._用易写isapi的筛选器,iis防盗链,谁会?讨论一下

python是什么和c++是什么区别_C++、Java和Python有什么不同?-程序员宅基地

文章浏览阅读2.5k次,点赞2次,收藏5次。C++、Java和Python都是面向对象的编程语言。其中C++和Java都是强类型语言,而Python是一种弱类型语言。一、python: 快速开发应用程序python比较容易学习,语法很简单,融入了很多现代编程语言的特性。python的库非常丰富,可以迅速地开发程序,无论是网站还是小游戏都非常方便。不过,python的脚本的运行效率较低,不适合对运行效率要求较高的程序。Python是一种脚本语..._python和c++什么关系

随便推点

shell脚本循环语句_shell脚本按次数循环-程序员宅基地

文章浏览阅读590次。循环语句常用于重复执行一条命令或一组命令等,直到达到结束条件后,则终止执行。在Shell中常见的循环命令有while、until、for和select等。for循环语句​ for循环语句与while循环语句类似,但for循环语句主要用于有限次的循环场景,while主要无限次循环的场景,如守护进程。for循环语句语法分析第一种格式for 变量 in 列表do操作done第二种..._shell脚本按次数循环

gensim函数训练Word2Vec模型 具体参数讲解_gensim word2vec 参数-程序员宅基地

文章浏览阅读2.9k次。用gensim函数库训练Word2Vec模型有很多配置参数。这里对gensim文档的Word2Vec函数的参数说明进行翻译。class gensim.models.word2vec.Word2Vec(sentences=None,size=100,alpha=0.025,window=5, min_count=5, max_vocab_size=None, sample=0.001,seed=..._gensim word2vec 参数

Vue.js概述_vue.js是动态页面吗-程序员宅基地

文章浏览阅读265次。从头开始复习Vue.js3_vue.js是动态页面吗

django restframework ModelViewSet PUT方法不被允许_方法 “put” 不被允许。-程序员宅基地

文章浏览阅读4.1k次。默认的viewset和默认的router,但发送put、delete请求提示不支持官方实现update方法的时候要求传入pk,所以在put时将请求URL改成:path/pk/就可以了。正确的传参方式retrieve get/id/update put/id/destroy delect/id/list getpartial_update patchcreate post如果格式不正确 会显示" put 方法 不被允许..._方法 “put” 不被允许。

使用AD14创建异形PCB板_ad14导入dwg-程序员宅基地

文章浏览阅读7.8k次,点赞3次,收藏8次。前段时间同事需要按照AutoCAD的尺寸做一个PCB板。AD14支持导入DWG文件,于是选择了直接导入文件的方式来获得PCB板的外形尺寸。AutoCAD的尺寸图如下:打开Altium Designer 14.1,新建一个空白的PCB图。然后单击File->Import...打开导入文件对话框,在对话框里面文件类型选择AutoCAD(*.DXF, *.DWG),选_ad14导入dwg

【NOJ1001】【算法实验一】二分查找_给定递增整数序列l,其大小为n,要求使用二分查找法查找任意元素的位置k(序列中第几-程序员宅基地

文章浏览阅读533次。1001.二分查找时限:1000ms 内存限制:10000K 总时限:3000ms描述给定一个单调递增的整数序列,问某个整数是否在序列中。输入第一行为一个整数n,表示序列中整数的个数;第二行为n(n不超过10000)个整数;第三行为一个整数m(m不超过50000),表示查询的个数;接下来m行每行一个整数k。输出每个查询的输出占一行,如果k在序列中,输出Yes,否则输出No。输入样例51 3 4 7 113369输出样例YesNoNo#include <iostr_给定递增整数序列l,其大小为n,要求使用二分查找法查找任意元素的位置k(序列中第几