游戏编程数学和物理基础(相关函数)

功能:判断一个数字是否是2的n次幂
输入:待检测的数字
输出:如果该数字为2的n次幂则返回true,否则返回false
bool powOfTwo(int num)
{
	return !(num &(num-1));
}

用来存储点的一些数据类型
1.浮点数数组,优点是速度快、简单和内存开销低
float 3dPoint[3];
2.包含3个浮点数的结构体,优点是可以重载运算符和自定义函数
struct 3dPoint
{
	float x, y, z;


	//重载加号运算符
	3dPoint operator + (const 3dPoint &P2) const
	{
		3dPoint temp = { this->x+P2.x;
						 this->y+P2.y;
						 this->z+P2.z;
						};
		return temp;
	}
};

功能:计算给定两点之间的斜率
输入:P1-第一个点(具有两个浮点值的数组) P2-第二个点(具有两个浮点值的数组)
输出:两点之间的斜率
float slpoeBetweenPoints(float *P1,float *P2)
{
	return (P2[1]-P1[1])/(P2[0]-P1[0]);
}

功能:计算与给定直线相垂直直线的斜率
输入:slope-给定直线的斜率
输出:与给定直线相垂直直线的斜率
float perpSlope(float slope)
{
	return -1/slope;
}


功能:判断两条直线是否相互垂直
输入:slope1-第一条直线的斜率 slope2-第二条直线的斜率
输出:如果两直线相互垂直则返回true,否则false

bool arePerp(float slope1,float slope2)
{
	if(slope1 * slope2 == -1)
	{
		return true;
	}
	else
	{
		return false;
	}
}

功能:找到两条直线的交点
输入:L1Point-位于第一条直线上的一个2D点 L1Slope-第一条直线的斜率 L2Point-位于第二条直线上的一个2D点 L2Slope-第二条直线的斜率
输出:保存直线交点的浮点数组
float* lineIntersect(float* L1Point,float L1Slope,
					 float* L2Point,float L2Slope)
{
	//临时数组,用于保存结果
	float* temp = new float[2];


	//求解x的值
	temp[0] = (L1Slope * L1Point[0] - L2Slope *L2Point[0] +
			   L2Point[1] - L1Point [1]) / (L1Slope - L2Slope);


	//利用刚求出的x计算y的值
	temp[1] = L1Slope * (temp[0] - L1Point[0]) + L1Point[1];


	return temp;
}

在下面函数中用两个双精度的数组代表2D空间中的点,并返回它们的距离值。注意,在头文件<cmath>中的函数sqrt()返回输入参数的平方根。另外,函数pow()带有两个参数,
并返回以第一个参数为底,第二个参数为幂的乘方的值。虽然函数pow()比乘法运算稍慢一些,但它还是很有用的。例如,虽然pow(x,2)比直接计算x*x运算的要慢一些,但如果
使用微软编绎器中#pragma  intrinsic预编绎命令,那么程序的速度将会大大提高。
#pragma intrinsic(sqrt,pow)
这一命令不再经过堆栈,而直接将数学运算送入运算器中。(更多关于intrinsic命令的信息,可以参阅MSDN。)注意,为了避免编绎器在双精度数据转化为单精度时因数据
丢失而发出警告,这一指令在返回值前首先将结果转换成单精度的数值。同样,由于sqrt()和powf()的输入输出都是单精度的,也可以使用这两个函数来避免编绎器警告。
功能:计算两点之间的距离
输入:P1-表示点1的实型数组 P2-表示点2的实型数组
输出:两点之间的距离
float distance2D(float *P1,float *P2)
{
	//计算并返回所求距离
	return (float)sqrt(pow((P2[0] - P1[0]),2) + pow(P2[1] - P1[1],2));
}

下面这个函数带有两个参数P1、P2,并返回它们的中点。在这个函数中,用关键字new为变量temp分配存储空间,当不再需要这些内存时,可以使用关键字delete清除内存。由于
我们在分配内存时使用了括号,所以在清理时同样需要加上括号:delete[] temp;
功能:计算中点坐标
输入:P1-表示点1的实型数组 P2-表示点2的实型数组
输出:两点的中点坐标
float* find2DMidPoint(float *P1,float *P2)
{
	//为指针分配足够的空间
	float *temp = new float[2];
	
	//计算中点坐标
	temp[0] = (P1[0] + P2[0])/2.0f;
	temp[1] = (P1[1] + P2[1])/2.0f;

	//返回结果
	return temp;
}

功能:计算3维空间的中点坐标
输入:P1-表示点1的实型3维数组 P2-表示点2的实型3维数组
输出:两点的中点坐标
float* find3DMidPoint(float *P1,float *P2)
{
	//为指针分配足够的空间
	float *temp = new float[3];


	//计算中点坐标
	temp[0] = (P1[0] + P2[0])/2.0f;
	temp[1] = (P1[1] + P2[1])/2.0f;
	temp[2] = (P1[2] + P2[2])/2.0f;

	//返回结果
	return temp;
}

圆和球的结构
struct circle	//圆
{
	float center[2];
	float radius;
};


struct sphere	//球
{
	float center[3];
	float radius;
};

下面的示例函数用于检测两球是否相撞。在这个例子中,我们可以很简单地使用前面定义的球结构体。注意,在计算球心距离时,
我们不再比较平方根,而是直接与半径的平方和比较。如果在每一帧中都需要对大量的球体进行碰撞检测,那么这个简便而又有效
的方法将会大大加速程序的运行。
功能:检测两球是否发生碰撞
输入:S1-第一个球 S2-第二个球
输出:假如发生碰撞,返回真,否则为假
bool ColBetweenSpheres(sphere &S1,sphere &S2)
{
	return (pow(S2.center[0] - S1.center[0],2) +
			pow(S2.center[1] - S1.center[1],2) +
			pow(S2.center[2] - S1.center[2],2) <
			pow(S1.radius + S2.radius,2));
}
(注意,在这个函数中并没有用到if-else条件分支结构。这是因为return后面的不等式如果成立,程序会自动输出true,如果不成
立,也会自动输出false。)

功能:检测两圆是否发生碰撞
输入:ball2-用于检测碰撞的球
输出:如果与其他球发生碰撞则返回真

bool Ball:checkBallCollision(Ball &ball2)
{
	//球的半径
	int radius1 = diameter/2;
	int radius2 = ball2.diameter/2;


	//第一个球的球心
	POINT center1;
	center1.x = radius1 + bounds.left;
	center1.y = radius1 + bounds.top;


	//第二个球的球心
	POINT center2;
	center2.x = radius2 + ball2.bounds.left;
	center2.y = radius2 + ball2.bounds.top;


	//两球之间的距离
	double distance = sqrt(SQUARE(center2.x - center1.x)+SQUARE(center2.y - center1.y));


	//检测是否发生碰撞
	if (distance<=radius1+radius2)
	{
		return true;
	}
	else
	{
		return false;
	}
}

角度和弧度之间的转换
#define RadToDeg 57.29577951f
#define DegToRad 0.017453293f
在这里给大家介绍一个技巧,在真正进入游戏主循环之前,通常我们可以建立一个三角函数查找表,这样在游戏当中需要三角函数数值的时候就不用再重新计算了,
只需查找对应的表格就行了,该技巧可以大大加快程序的运行速度。下面就是一个创建三角函数查找表的例子。
该数组将保存三角函数值
float sin_table[360];
//填充表格
for(int i=0;i<360;++i)
{
	//请记住我们在前面定义的宏DegToRad
	sin_table[i] = sin(i*DegToRad);
}
//计算任意角度的正弦值
float value = sin_table[abs((int)angle)%360];
首先将角度angle强制转换成一个整形值,然后取其绝对值,再对其进行模360运算,以此为索引查找正弦表即可。通过取模运算就不用限制角度的大小了,同时也就
不会发生数组下标越界的错误。另外,还有一点要注意,如果你在程序中使用预编译命令#pragma intrinsic指示编绎器将三角函数编译成内联函数的话,那么利用查找
表而进行的优化也就会变得不再明显了。
#pragma intrinsic(sin,cos,tan)

功能:计算2D空间内两个物体之间的角度
输入:P1-第一个物体的位置 P2-第二个物体的位置
输出:两个物体之间的角度
float calcAngle2D(float *P1,float *P2)
{
	//计算标准角
	float ang=(float)atan((P2[1]-P1[1])/(P2[0]-P1[0])) * RadToDeg;
	//如果该角度在第一象限
	if (P2[1]<P1[1] && P2[0]>P1[0])
	{
		return ang;
	}
	//如果该角度位于第二、三象限
	else if((P2[1]<P1[1] && P2[0]<P1[0]) ||
		(P2[1]>P1[1] && P2[0]<P1[0]))
	{
		return ang+180;
	}
	else
	{
		return ang+360;
	}
}
角的正弦值在第一、第二象限为正值,角的余弦值在第一、第四象限为正值,角的正切值在第一、第三象限为正值。对于所有的反三角函数,如果传入的参数是一个正值,
那么它们的返回值都为正,即意味该角位于第一象限vk果传入的参数为负数,那么反正弦asin()和反正切atan()的返回角度将位于第四象限,而反余弦acos()的返回角度位
于第二象限。因而在实例中,我们必须弄清楚物体的实际位置,确定角度所处的正确的象限,然后通过加上180度或360度计算出它在标准位置的角度值。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值